SuFi
SuFi

Reputation: 385

Mongodb Search with embedded document.

Structure of mongodb collection is like this.
collection User

{
"name":"sufaid",
"age":"22",
"address":"zzzz",
"product":[{"id":1,"name":"A"},
            {"id":6,"name":"N"},
            {"id":3,"name":"D"},
            {"id":7,"name":"q"},
        ]
}  

I need to find users those who have product id "3"

Out put should be like this

{
    "name":"sufaid",
    "age":"22",
    "address":"zzzz",
    "product":{"id":3,"name":"D"}
    } 

Note : With out using $unwind and projection like "product.$"

"product.$" through error while using pymongo.
Any other option is there ???

Upvotes: 1

Views: 68

Answers (3)

cartman619
cartman619

Reputation: 552

use $elemMatch. https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/

for your query:

db.User.find({},{name:1,age:1,address:1,product:{$elemMatch:{id:3}}})

or

db.User.find({},{product:{$elemMatch:{id:3}}})

o/p:    { 
    "name" : "sufaid", 
    "age" : "22", 
    "address" : "zzzz", 
    "product" : [
        {
            "id" : 3.0, 
            "name" : "D"
        }
    ]

}

As you require it for aggregation:

db.User.aggregate([
{$unwind:'$product'},
{$match:{'product.id':3}},
{$project:{_id:0,name:1,age:1,aaddress:1,product:1}}
])

o/p:

    { 
    "name" : "sufaid", 
    "age" : "22", 
    "address" : "zzzz", 
    "product" : {
        "id" : 3.0, 
        "name" : "D"
    }
}

This will give exactly what you indicated in the question.

Upvotes: 4

chridam
chridam

Reputation: 103325

You could use the aggregation framework which has a plethora of operators that you can use, in particular you'd need the $filter and $arrayElemAt operators in a $project pipeline.

For instance, you could return just the product field as an embedded document by running the following pipeline:

db.user.aggregate([
    { "$match": { "product.id": 3 } },
    {
        "$project": {
            "name": 1,
            "age": 1,
            "address": 1,
            "product": {
                "$arrayElemAt": [
                    {
                        "$filter": {
                            "input": "$product",
                            "as": "item",
                            "cond": { "$eq": [ "$$item.id", 3 ] }
                        }
                    },
                    0
                ]
            }
        }
    }
])

Sample Output

{
    "_id" : ObjectId("5829ac89628123dcf8a64b7a"),
    "name" : "sufaid",
    "age" : "22",
    "address" : "zzzz",
    "product" : {
        "id" : 3,
        "name" : "D"
    }
}

If you just need an output with the array filtered, skip the $arrayElemAt expression and use the $filter only:

db.user.aggregate([
    { "$match": { "product.id": 3 } },
    {
        "$project": {
            "name": 1,
            "age": 1,
            "address": 1,
            "product": {
                "$filter": {
                    "input": "$product",
                    "as": "item",
                    "cond": { "$eq": [ "$$item.id", 3 ] }
                }
            }
        }
    }
])

Sample Output

{
    "_id" : ObjectId("5829ac89628123dcf8a64b7a"),
    "name" : "sufaid",
    "age" : "22",
    "address" : "zzzz",
    "product" : [
        { "id" : 3, "name" : "D" }
    ]
}

Upvotes: 2

SuFi
SuFi

Reputation: 385

db.User.find({},{product:{$elemMatch:{id:3}}})

it's enough

Upvotes: 0

Related Questions