在Apollo GraphQL解析器中使用的父级参数与MongoDB聚合中的$lookup阶段用于连接Mongoose模型的比较
P粉543344381
2023-09-02 09:22:26
<p>我正在使用 Apollo GraphQL 和 Mongoose 开发后端应用程序。我有两个模型:User 和 Post,它们具有一对多关系(一个用户可以有多个帖子,但一个帖子属于一个用户)。</p>
<p>我想查询 GraphQL 架构中的用户字段,以按用户 ID 获取用户以及属于该用户的所有帖子。我还想查询我的帖子类型中的作者字段以获取撰写该帖子的用户。</p>
<p>我了解到,有两种方法可以连接 MongoDB 中不同集合的数据:使用 Apollo GraphQL 解析器中的父参数,或使用 MongoDB 聚合中的 $lookup 阶段。</p>
<p>父参数是一个对象,其中包含从父字段上的解析器返回的结果。父参数可用于访问父字段或类型中的数据,并将其传递给子字段或类型。例如,我可以使用它来加入猫鼬模型,如下所示:</p>
<pre class="brush:php;toolbar:false;">type User {
id: ID!
name: String
posts: [Post]
}
type Post {
id: ID!
title: String
author: User
}
type Query {
user(id: ID!): User
}
const resolvers = {
User: {
posts(parent, args, context) {
return context.db.Post.find({ author: parent.id });
},
},
};</pre>
<p>$lookup 阶段是一个聚合管道阶段,它对同一数据库中的另一个集合执行左外连接。 $lookup 阶段可用于将多个集合中的数据合并到单个结果集中。例如,我可以使用它来加入这样的模型:</p>
<pre class="brush:php;toolbar:false;">db.posts
.aggregate([
{
$lookup: {
from: "users",
localField: "author",
foreignField: "_id",
as: "author",
},
},
])
.toArray((err, posts) => {
console.log(posts);
});</pre>
<p>我不确定我的应用程序应使用哪一个。我想选择更高效、可扩展和可维护的选项。</p>
<p>在 Apollo GraphQL 解析器中使用父参数和在 MongoDB 聚合中使用 $lookup 阶段来加入 Mongoose 模型之间的主要区别和权衡是什么?</p>
我推荐第一种技术 - 它肯定更干净并且可能更快。您应该确保为
author
字段建立索引 - 就像在 RDB 中为外键建立索引一样。这两种方法之间确实存在一些差异
使用解析器
我发现这种方法更直观、更具可读性,因此更易于维护,尤其是对于复杂的查询
但是,在处理大量数据时,它可能不是最有效的,因为它会为每个嵌套字段对数据库进行额外的调用。在处理大量复杂的嵌套查询时,这可能会成为性能瓶颈。
使用$lookup
另一方面,$lookup 操作通常性能更高,因为它们使用单个数据库调用来连接和检索数据。
但是,随着查询复杂性的增加,$lookup 操作可能会变得复杂且难以阅读和维护。它可能需要更多关于 MongoDB 查询语言的知识,并且可能不像解析器方法那样简单易用。写得不好的聚合可能会导致性能问题,所以要绝对确定你在做什么。
因此,在您的示例中,我不介意使用解析器方法,即使使用聚合速度更快,第一种方法也会更容易阅读/改进/维护。
希望有帮助:)