Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 834
khushboo Avatar asked Sep 28 '18 07:09

khushboo


People also ask

How does $lookup work in MongoDB?

Speak with an Expert for Free When you’re querying data in MongoDB, there are times when you need information that’s stored in documents across multiple collections. The $lookup function makes it easy to “join” multiple collections, returning results that contain fields from all specified collections.

How do I join two MongoDB collections and retrieve fields?

When you need to join two MongoDB collections and retrieve fields from documents stored in both of them, the $lookup function can help you target the right data and get the results you want. In this article, we provided a basic overview of the $lookup function in MongoDB and walked through some examples of how to use the function.

What are multiple join conditions in MongoDB?

Multiple join conditions. Correlated and uncorrelated subqueries. In MongoDB, a correlated subquery is a pipeline in a $lookup stage that references document fields from a joined collection. An uncorrelated subquery does not reference joined fields.

What is the difference between and and or conditions in MongoDB?

The AND condition displays only those records where both condition 1 and condition 2 are met. The OR condition displays those records if any one of the conditions is met. The IN condition takes multiple values and based on these values, records are displayed. Prerequisites. MongoDB 4.4.0, MongoDB Setup. Sample Data


2 Answers

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"
    }
}])
like image 99
dnickless Avatar answered Oct 18 '22 23:10

dnickless


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] }
      }
    }
  }}
])
like image 3
Ashh Avatar answered Oct 18 '22 23:10

Ashh