GraphQL查询与表连接

我正在学习GraphQL所以我build立了一个小项目。 比方说,我有2个模型, UserComment

 const Comment = Model.define('Comment', { content: { type: DataType.TEXT, allowNull: false, validate: { notEmpty: true, }, }, }); const User = Model.define('User', { name: { type: DataType.STRING, allowNull: false, validate: { notEmpty: true, }, }, phone: DataType.STRING, picture: DataType.STRING, }); 

关系是1:很多,用户可以有很多评论。
我已经build立了这样的架构:

 const UserType = new GraphQLObjectType({ name: 'User', fields: () => ({ id: { type: GraphQLString }, name: { type: GraphQLString }, phone: { type: GraphQLString }, comments: { type: new GraphQLList(CommentType), resolve: user => user.getComments() } }) }); 

和查询:

 const user = { type: UserType, args: { id: { type: new GraphQLNonNull(GraphQLString) } }, resolve(_, {id}) => User.findById(id) }; 

执行一个用户的查询和他的意见是由1请求完成,如下所示:

 { User(id:"1"){ Comments{ content } } } 

据我所知,客户将得到使用1查询的结果,这是使用GraphQL的好处。 但服务器将执行2个查询,一个用于用户,另一个用于他的评论。
我的问题是,什么是build立GraphQL模式和types和组合表之间的GraphQL的最佳做法,以便服务器也可以执行查询1请求?

您所指的概念称为批处理。 有几个图书馆提供这个。 例如:

  • Dataloader :由Facebook维护的通用实用程序,提供“通过各种后端一致的API,并通过批处理和caching减less对后端的请求”

  • join-monster :“批量数据抓取的GraphQL到SQL查询执行层”

对于任何使用.NET和GraphQL for .NET软件包的人来说,我已经制作了一个将GraphQL Query转换为Entity Framework Includes的扩展方法。

 public static class ResolveFieldContextExtensions { public static string GetIncludeString(this ResolveFieldContext<object> source) { return string.Join(',', GetIncludePaths(source.FieldAst)); } private static IEnumerable<Field> GetChildren(IHaveSelectionSet root) { return root.SelectionSet.Selections.Cast<Field>().Where(x => x.SelectionSet.Selections.Any()); } private static IEnumerable<string> GetIncludePaths(IHaveSelectionSet root) { var q = new Queue<Tuple<string, Field>>(); foreach (var child in GetChildren(root)) { q.Enqueue(new Tuple<string, Field>(child.Name.ToPascalCase(), child)); } while (q.Any()) { var node = q.Dequeue(); var children = GetChildren(node.Item2).ToList(); if (children.Any()) { foreach (var child in children) { q.Enqueue(new Tuple<string, Field>(node.Item1 + "." + child.Name.ToPascalCase(), child)); } } else { yield return node.Item1; } } } } 

可以说我们有以下查询:

 query { getHistory { id product { id category { id subCategory { id } subAnything { id } } } } } 

我们可以在字段的“parsing”方法中创build一个variables:

 var include = context.GetIncludeString(); 

它会生成以下string:

 "Product.Category.SubCategory,Product.Category.SubAnything" 

并传递给Entity Framwork:

 public Task<TEntity> Get(TKey id, string include) { var query = Context.Set<TEntity>(); if (!string.IsNullOrEmpty(include)) { query = include.Split(',', StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (q, p) => q.Include(p)); } return query.SingleOrDefaultAsync(c => c.Id.Equals(id)); }