[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'}}]

并在 dbshel​​l 上进行了尝试

#> 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'。 希望能说清楚我的需求

您有两个选择:

  1. find 查询中使用 $elemMatch。 (要小心,因为 $elemMatch 只有 returns 数组中的一个对象)

您可以使用此查询:

db.collection.find({
  "_id": "Toy"
},
{
  "child": {
    "$elemMatch": {
      "isActive": "1"
    }
  }
})

示例[https://mongoplayground.net/p/du7FTnvlW7C]

但还要检查 this example 有两个 isActive: "1" 而只返回一个。

  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.