Here is one of the document from which i would like get all the child.item ('Toy1','Toy2' etc) in a list.
{
_id: 'Toy',
name: 'Toyname',
child: [
{ item: 'Toy1', isActive: '1', Type: 'New' },
{ item: 'Toy2', isActive: '2', Type: 'Old' }
]
}
I have tried
pipeline = [
{
"$match": {
"_id": "Toy",
"child.isActive": '1'
}
},
{
"$unwind":
"$child"
},
]
list(DB.Category.aggregate(pipeline))
[{'_id': 'Toy', 'name': 'Toyname', 'child': {'item': 'Toy1', 'isActive': 1, 'Type': 'New'}}, {'_id': 'Toy', 'name': 'Toyname', 'child': {'item': 'Toy2', 'isActive': 2,
'Type': 'Old'}}]
And tried this on dbshell
#> db.Category.find({name:"Toyname",child:{$elemMatch:{Type:"New"} }})
[
{
_id: 'Toy',
name: 'Toyname',
child: [
{ item: 'Toy1', isActive: '1', Type: 'New' },
{ item: 'Toy2', isActive: '2', Type: 'Old' }
]
}
]
But as you can see it gives me both the items from the array. I am using pymongo 4.0.1.
Expecting a list as o/p which fulfilled match criteria like Type:'New' in $match should return 'Toy1' and isActive:'2' should return 'Toy2'. I hope i am able to put my requirement clearly.
CodePudding user response:
You have two options:
- Using $elemMatch in a
findquery. (Be careful because$elemMatchonly returns one object from the array)
You can use this query:
db.collection.find({
"_id": "Toy"
},
{
"child": {
"$elemMatch": {
"isActive": "1"
}
}
})
Example [https://mongoplayground.net/p/du7FTnvlW7C]
But also check this example where there are two isActive: "1" and only one is returned.
- Using $filter in an aggregate query (also you can use
$match,$unwindand$grouptogether but I think using$filteris a better way).
So using aggregate you can try this query:
db.collection.aggregate([
{
"$match": {
"_id": "Toy"
}
},
{
"$addFields": {
"child": {
"$filter": {
"input": "$child",
"as": "c",
"cond": {
"$eq": ["$$c.isActive","1"]
}
}
}
}
}
])
Example here
And using $unwind you need this query which I think is too heavy: two $match, an $unwind and a $group... when you can only use $filter.
