0

I am trying to find whether a user is liked a product or not while fetching the products from a collection using $lookup operation to search for like which is in a likes collection consists of two fields productId(likedProduct) and userID(who liked the product) both productId and userId are of type ObjectId this is my schema for products

const products = new mongoose.Schema({
created: {
    type: Date,
    default: Date.now()
},
images: [{
    type: String
}]
});

and likes Schema

new Schema({
userId: {
    type: Schema.Types.ObjectId,
    required: true,
    index: true
},
productId: {
    type: Schema.Types.ObjectId,
    required: true,
    index: true,
    ref: 'products'
},
created: {
    type: Date,
    default: Date.now()
}
});

I have tried using $lookup operator as

const { user } = req;
productsModels.aggregate([
            { $sort: { '_id': -1 } },
            { $limit: 10 },
            {
                $lookup: {
                    from: 'likes',
                    pipeline: [
                        {
                            $match: {
                                'productId': '$_id',
                                'userId':user.id
                            }
                        }
                    ],
                    as: 'liked'
                }
            },
        ]);}

but it's not giving me the expected result even though the user has liked the product and I got liked as an empty array!

{
created: "2019-08-30T10:46:53.692Z"
images: ["8f3447bb-8bb8-4c5a-acde-bcdc1b729c09"]
liked: []
price: 9
title: "developer"
userId: "5d68fea345353e1748cf7a10"
__v: 0
_id: "5d68fec745353e1748cf7a12"}

Thanks in advance

Nikhil Ponduri
  • 409
  • 9
  • 28
  • 1
    See also [Specify Multiple Join Conditions with `$lookup`](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#specify-multiple-join-conditions-with-lookup) in the `$lookup` pipeline stage documentation. You basically are missing the `$expr` operator for the comparison of `product_id` to the `_id` of the parent document. The `user.id` part is *probably* okay as long as that points to a value which is already an `ObjectId`. – Neil Lunn Aug 31 '19 at 01:28

1 Answers1

1

Try this

const { user } = req;

productsModels.aggregate([
            { $sort: { '_id': -1 } },
            { $limit: 10 },
            {
                $lookup: {
                    from: 'likes',
                    let: {productId:"$_id"},
                    pipeline: [
                        {
                            $match: {
                                $expr:{$eq:['$_id', '$$productId']}},
                                'userId': mongoose.Type.Object(user.id)
                            }
                        }
                    ],
                    as: 'liked'
                }
            },
        ]);}

In your query two things where missing

1) Converting userid to mongo object id so we used mongoose.Types.ObjectId

2) You can't use outer collection field directly in inner pipeline for this you have create temp variable so we used let to declare and to match with internal field we need to use $expr

Jits
  • 545
  • 3
  • 12