0

I am using mongo v3.4.4
How do I get the object of an array.
Collection sample

{
    name: earth
    age: 12
    cars : [
        {
            brand : tesla
            color : red
            time : 123
        },
        {
            brand : toyota
            color : black
            time : 124
        },
    ]

},
{
    name: mars
    age: 15
    cars : [
        {
            brand : volvo
            color : green
            time : 125
        },
        {
            brand : honda
            color : blue
            time : 126
        },
    ]
}

What I need is only:

{
    brand : tesla
    color : red
    time : 123
}

I have tried:

db.users.aggregate([
    {
        $match:{"name":"earth"}
    },
    {
        $project:
            {"cars":
                {"$filter":
                    {
                      input:"$cars", 
                      as:"cars", 
                      condition: "{$eq:[ $$cars.brand :"tesla"]}"
                      }
                 }
            }
      }
 ])

However, I still don't see the output that I expected. I am not sure if I am not using the filters correctly. If there is only one object in the cars array, then I would only return that one object. I have looked at this example

WarrenV
  • 220
  • 1
  • 2
  • 9
  • 1
    You don't need `$filter` here for a "single" match. If you read "all" the answers given you should have seen `.find({ "name": "earth", "cars.brand": "tesla" },{ "brand.$": 1 })` which will return the same thing. As for it "not being what you want", then get used to it! You after-all are the one who decided to embed the documents in an array in the first place. If you expect to only retrieve "just" the embedded document that matches, then "you" should have put them in a separate collection instead. Could you do it? Yes. Should you do it? No. Just match the data and extract the item in your code – Neil Lunn Jul 10 '17 at 05:41

3 Answers3

1

You can use following aggregation pipeline:

db.users.aggregate([
 {$match: {name:"earth"}},
 {$unwind: "$cars"},
 {$replaceRoot: {newRoot: "$cars"}},
 {$match: {brand:"tesla"}}
]);
Sankalp Bhatt
  • 1,024
  • 13
  • 17
1

Use below aggregate query:

 db.users.aggregate({$match:{name:'earth'}},{$unwind:"$cars"},{$match:{"cars.name":'tesla'}},{$project:{"cars":"$cars",_id: 0}});

result would be like this

{ "cars" : { "name" : "tesla", "color" : "red" } }
Nalla Srinivas
  • 853
  • 1
  • 9
  • 17
1

I would say instead of using aggregation you can achieve by normally using below query

db.users.find({ "name":"earth" }, { "cars" : { "$elemMatch" : { "name" : "tesla }}})

And your output will be,

{
   "cars" : [ 
    {
       brand : tesla
       color : red
       time : 123
    }]
}

Aggregation is always an costly operation

venkat.s
  • 90
  • 1
  • 6