[pymongo]:在对象数组中查找项目
[pymongo]: Find items in array of objects
这是一份文档,我想从中获取列表中的所有 child.item('Toy1'、'Toy2' 等)。
{
_id: 'Toy',
name: 'Toyname',
child: [
{ item: 'Toy1', isActive: '1', Type: 'New' },
{ item: 'Toy2', isActive: '2', Type: 'Old' }
]
}
我试过了
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'}}]
并在 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' }
]
}
]
但是如您所见,它为我提供了数组中的两个项目。我正在使用 pymongo 4.0.1.
期望列表为 o/p 满足匹配条件,例如 Type:'New' in $match should return 'Toy1' and isActive:'2' should return 'Toy2'。
希望能说清楚我的需求
您有两个选择:
- 在
find
查询中使用 $elemMatch。 (要小心,因为 $elemMatch
只有 returns 数组中的一个对象)
您可以使用此查询:
db.collection.find({
"_id": "Toy"
},
{
"child": {
"$elemMatch": {
"isActive": "1"
}
}
})
示例[https://mongoplayground.net/p/du7FTnvlW7C]
但还要检查 this example 有两个 isActive: "1"
而只返回一个。
- 在聚合查询中使用 $filter(您也可以同时使用
$match
、$unwind
和 $group
,但我认为使用 $filter
更好方式)。
所以使用 aggregate
你可以试试这个查询:
db.collection.aggregate([
{
"$match": {
"_id": "Toy"
}
},
{
"$addFields": {
"child": {
"$filter": {
"input": "$child",
"as": "c",
"cond": {
"$eq": ["$$c.isActive","1"]
}
}
}
}
}
])
示例here
并且使用 $unwind
你需要 this query,我认为它太重了:两个 $match
,一个 $unwind
和一个 $group
... 当你只能使用 $filter
.
这是一份文档,我想从中获取列表中的所有 child.item('Toy1'、'Toy2' 等)。
{
_id: 'Toy',
name: 'Toyname',
child: [
{ item: 'Toy1', isActive: '1', Type: 'New' },
{ item: 'Toy2', isActive: '2', Type: 'Old' }
]
}
我试过了
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'}}]
并在 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' }
]
}
]
但是如您所见,它为我提供了数组中的两个项目。我正在使用 pymongo 4.0.1.
期望列表为 o/p 满足匹配条件,例如 Type:'New' in $match should return 'Toy1' and isActive:'2' should return 'Toy2'。 希望能说清楚我的需求
您有两个选择:
- 在
find
查询中使用 $elemMatch。 (要小心,因为$elemMatch
只有 returns 数组中的一个对象)
您可以使用此查询:
db.collection.find({
"_id": "Toy"
},
{
"child": {
"$elemMatch": {
"isActive": "1"
}
}
})
示例[https://mongoplayground.net/p/du7FTnvlW7C]
但还要检查 this example 有两个 isActive: "1"
而只返回一个。
- 在聚合查询中使用 $filter(您也可以同时使用
$match
、$unwind
和$group
,但我认为使用$filter
更好方式)。
所以使用 aggregate
你可以试试这个查询:
db.collection.aggregate([
{
"$match": {
"_id": "Toy"
}
},
{
"$addFields": {
"child": {
"$filter": {
"input": "$child",
"as": "c",
"cond": {
"$eq": ["$$c.isActive","1"]
}
}
}
}
}
])
示例here
并且使用 $unwind
你需要 this query,我认为它太重了:两个 $match
,一个 $unwind
和一个 $group
... 当你只能使用 $filter
.