khushboo
khushboo

Reputation: 715

Apply condition in $lookup in mongodb

I'm new in mongoDb. I have set two collections. 1) book 2) comments

book : 
_id
title
author
posted
price

And comments is :

_id
bookId
comment
status

I want to get get those book's comment which has status = 1.

I have tried this.

return new promise((resolve, reject) => {
    db.collection('book').aggregate([
        {
            $lookup:{
                from:'comments',
                localField: "_id",
                foreignField: "bookId",
                as: "comments"                                                                  
            }
        }      
    ]).toArray().then((result) => {
        if(result.length > 0){
            res.send({ status: 1, message: "Success.", data:result });
        }else{
            res.send({ status: 0, message: "No data found." });
        }
    }).catch((err) => {
        res.send({ status: 0, message: "Something went wrong."});
    });
});

And when I call my API , I got this out in postman.

{
"status": 1,
"message": "Success.",
"data": [
    {
        "_id": "5bacad201bff841afb40791f",
        "title": "Game of thrones",
        "author": "John snow",
        "posted": "16/07/1995",
        "price": 1000,
        "comments": [
            {
                "_id": "5bacc31aa2d365256cab31ce",
                "bookId": "5bacad201bff841afb40791f",
                "comment": "Winter is comming"
            },
            {
                "_id": "5bacc3f65c716925df953615",
                "bookId": "5bacad201bff841afb40791f",
                "comment": "It has a level of politics"
            },
            {
                "_id": "5bacd60ea38cc526f1fee1d1",
                "bookId": "5bacad201bff841afb40791f",
                "comment": "It has a level of politics",
                "status": 1
            }
        ]
    },
    {
        "_id": "5bacad601bff841afb407920",
        "title": "Breaking bed",
        "author": "Haison burg",
        "posted": "20/08/2002",
        "price": 550,
        "comments": []
    }
]
}

I need data which comments has status 1 value. I have tried to use $match after $lookup but it not works. I have also tried to use $eq which is also not works for me. It may possible that I set it in a wrong way due to I have just start learning mongodb.

Upvotes: 5

Views: 7925

Answers (2)

dnickless
dnickless

Reputation: 10918

From MongoDB v3.6.3 onwards, the fastest query performance would be achieved like this:

Make sure you have an index on the bookId and the status fields in the comments collection:

db.comments.createIndex({ "bookId": 1, "status": 1 })

And then use the new pipeline attribute of the $lookup stage (documentation):

db.books.aggregate([{
    "$lookup": {
        "from": "comments",
        "let": { "bId": "$_id" },
        "pipeline": [{
            "$match": {
                $expr: { $eq: [ "$bookId", "$$bId" ] },
                "status": 1
            }
        }],
        "as": "comments"
    }
}])

Upvotes: 4

Ashh
Ashh

Reputation: 46451

You can use $addFields and $filter aggregation here

db.collection("book").aggregate([
  { "$lookup": {
    "from": "comments",
    "localField": "_id",
    "foreignField": "bookId",
    "as": "comments"                                                                  
  }},
  { "$addFields": {
    "comments": {
      "$filter": {
        "input": "$comments",
        "cond": { "$eq": ["$$this.status", 1] }
      }
    }
  }}
])

Upvotes: 3

Related Questions