Comparison of parent parameters used in Apollo GraphQL resolver vs. $lookup stage in MongoDB aggregation for joining Mongoose models
P粉543344381
2023-09-02 09:22:26
<p>I'm developing a backend application using Apollo GraphQL and Mongoose. I have two models: User and Post, which have a one-to-many relationship (one user can have multiple posts, but one post belongs to one user). </p>
<p>I want to query the User field in a GraphQL schema to get a user by user ID and all posts belonging to that user. I also want to query the author field in my post type to get the user who wrote the post. </p>
<p>I learned that there are two ways to join data from different collections in MongoDB: using the parent parameter in the Apollo GraphQL resolver, or using the $lookup stage in a MongoDB aggregate. </p>
<p>The parent parameter is an object containing the results returned from the parser on the parent field. Parent parameters can be used to access data from a parent field or type and pass it to a child field or type. For example, I can use this to join a mongoose model like this: </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>The $lookup stage is an aggregation pipeline stage that performs a left outer join to another collection in the same database. The $lookup stage can be used to merge data from multiple collections into a single result set. For example, I can use it to join a model like this: </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>I'm not sure which one I should use for my application. I wanted to choose a more efficient, scalable and maintainable option. </p>
<p>What are the main differences and trade-offs between using parent parameters in the Apollo GraphQL resolver and using the $lookup stage in MongoDB aggregations to join Mongoose models? </p>
I recommend the first technique - it's definitely cleaner and probably faster. You should make sure to index the
author
field - just like you would index a foreign key in an RDB.There do exist some differences between the two methods
Use parser
I find this approach more intuitive and readable, and therefore easier to maintain, especially for complex queries
However, it may not be the most efficient when dealing with large amounts of data, as it will make additional calls to the database for each nested field. This can become a performance bottleneck when dealing with large numbers of complex nested queries.
Use $lookup
On the other hand, $lookup operations are generally more performant because they use a single database call to connect and retrieve data.
However, as query complexity increases, $lookup operations can become complex and difficult to read and maintain. It may require more knowledge of the MongoDB query language and may not be as simple and easy to use as the parser approach. Poorly written aggregates can cause performance issues, so be absolutely sure of what you're doing.
So in your example I don't mind using the parser approach, even though using aggregation is faster, the first approach will be easier to read/improve/maintain.
Hope it helps:)