Reputation: 1529
I'm trying to add a like feature to my site. I've made a likes collection with the following schema. I'm using custom _id to avoid creating an extra index.
{
_id: {
postId: ObjectId,
userId: ObjectId
}
}
I have a route on my server which searches the posts collection using MongoDB aggregations. I'm trying to add a $lookup stage to the current pipeline in order to add a liked property with the type of Boolean indicating wether or not the post has been liked by the user. Here's the $lookup stage which is not working (liked returns an empty array all the time even when there's a corresponding like document):
{
$lookup: {
from: 'likes',
let: { likedPostId: '$_id.postId', likerUserId: '$_id.userId' },
pipeline: [
{ $match:
{ $expr:
{ $and:
[
{ $eq: [
'$$likerUserId',
ObjectId('12345')
]},
{ $eq: [
'$$likedPostId',
'$_id'
]}
]
}
}
}
}
],
as: 'liked'
}
}
I think the problem is the variables don't actually hold the values I'm expecting them to. Is there any way to solve this? Also if you know a simpler way to implement this I'd appreciate if you share it with me.
I've tried comparing two identical ObjectId() instances to ensure ObjectId instances can be compared using $eq operator. Also tried defining nested variables like the ones in the code snippet above on a different nested field. the only different thing in this problem is that I'm trying to pull properties outside the _id field.
P.S. I know the liked property would be an Array instead of a Boolean. But I'm thinking of converting that into a Boolean in the next stage. But that's not the problem right now.
Upvotes: 4
Views: 11396
Reputation: 49985
It's the other way around. If you're running $lookup
on likes
collection then let
section's goal is to define variables that refer to the collection that you're running aggregation on. On the other hand you can refer to fields defined in likes
collection using single dollar sign inside of pipeline
. Try:
{
$lookup: {
from: 'likes',
let: { id: '$_id' },
pipeline: [
{ $match:
{ $expr:
{ $and:
[
{ $eq: [
'$_id.userId',
ObjectId('12345')
]},
{ $eq: [
'$_id.postId',
'$$id'
]}
]
}
}
}
],
as: 'liked'
}
}
EDIT: Please take a look at the docs
let
Optional. Specifies variables to use in the pipeline field stages. Use the variable expressions to access the fields from the documents input to the $lookup stage.The pipeline cannot directly access the input document fields. Instead, first define the variables for the input document fields, and then reference the variables in the stages in the pipeline.
Upvotes: 12