Python 使用elemmatch和filter执行pymongo查询

Python 使用elemmatch和filter执行pymongo查询,python,mongodb,pymongo,Python,Mongodb,Pymongo,我有以下数据结构: [ { "site_id": ObjectId("5e85b9d20498abd407e9a030"), "status": "ERROR" }, { "site_id": ObjectId("5e85b9d20498abd407e9a120"), "status": "ERROR" }, { "site_id": ObjectId("5e85b9d2049

我有以下数据结构:

[
    {
        "site_id": ObjectId("5e85b9d20498abd407e9a030"),
        "status": "ERROR"
    },
    {
        "site_id": ObjectId("5e85b9d20498abd407e9a120"),
        "status": "ERROR"
    },
    {
        "site_id": ObjectId("5e85b9d20498abd407e9a030"),
        "status": "OK",
        "risk_categories": [
            {

                "position": 1,
                "category_id": 1414,
            },
            {

                "position": 2,
                "category_id": 1402,

            },
            {

                "position": 3,
                "category_id": 1392,

            }
                ]
    }
]
我想用pymongo进行如下查询:

集合。查找一个(筛选器=筛选器)

其中: 筛选器={'$and':[{'$and':[{'site_id':ObjectId('5e85b9d20498abd407e9a030')},{'status':'OK'}},{'risk_categories':{'$elemMatch':{'$or':[{'position position':{'eq':1},{'position position':{'eq':2}}}}}}}

但是,它会返回整个对象。不仅仅是我想要的风险类别的价值。
我可以在我的过滤器上做什么来修改它

聚合从
mongo
shell运行:

db.collection.aggregate( [
  { 
      $match:  { 
          site_id: ObjectId('5e85b9d20498abd407e9a030'), 
          status: "OK" 
      } 
  },
  { 
      $addFields: {
          risk_categories: { 
              $filter: { 
                  input: "$risk_categories", 
                  as: "cat",
                  cond: {
                      $in: [ "$$cat.position", [ 1, 2 ] ]    // this is equivalent to using the "$or"
                  }
              }
          }
      }
  },
] ).pretty()
输出:

{
        "_id" : ObjectId("5e85c7b6724e461876467077"),
        "site_id" : ObjectId("5e85b9d20498abd407e9a030"),
        "status" : "OK",
        "risk_categories" : [
                {
                        "position" : 1,
                        "category_id" : 1414
                },
                {
                        "position" : 2,
                        "category_id" : 1402
                }
        ]
}


使用PyMongo 3.9和MongoDB 4.2,从Python shell:

import pymongo
from pymongo import MongoClient
client = MongoClient()
db = client.test
collection = db.collection
import pprint
from bson.objectid import ObjectId

pipeline = [
  { 
      '$match':  { 
          'site_id': ObjectId('5e85b9d20498abd407e9a030'), 
          'status': 'OK'
      } 
  },
  { 
      '$addFields': {
          'risk_categories': { 
              '$filter': { 
                  'input': '$risk_categories', 
                  'as': 'cat',
                  'cond': {
                      '$in': [ '$$cat.position', [ 1, 2 ] ]
                  }
              }
          }
      }
  },
]

pprint.pprint(list(collection.aggregate(pipeline)))

聚合从
mongo
shell运行:

db.collection.aggregate( [
  { 
      $match:  { 
          site_id: ObjectId('5e85b9d20498abd407e9a030'), 
          status: "OK" 
      } 
  },
  { 
      $addFields: {
          risk_categories: { 
              $filter: { 
                  input: "$risk_categories", 
                  as: "cat",
                  cond: {
                      $in: [ "$$cat.position", [ 1, 2 ] ]    // this is equivalent to using the "$or"
                  }
              }
          }
      }
  },
] ).pretty()
输出:

{
        "_id" : ObjectId("5e85c7b6724e461876467077"),
        "site_id" : ObjectId("5e85b9d20498abd407e9a030"),
        "status" : "OK",
        "risk_categories" : [
                {
                        "position" : 1,
                        "category_id" : 1414
                },
                {
                        "position" : 2,
                        "category_id" : 1402
                }
        ]
}


使用PyMongo 3.9和MongoDB 4.2,从Python shell:

import pymongo
from pymongo import MongoClient
client = MongoClient()
db = client.test
collection = db.collection
import pprint
from bson.objectid import ObjectId

pipeline = [
  { 
      '$match':  { 
          'site_id': ObjectId('5e85b9d20498abd407e9a030'), 
          'status': 'OK'
      } 
  },
  { 
      '$addFields': {
          'risk_categories': { 
              '$filter': { 
                  'input': '$risk_categories', 
                  'as': 'cat',
                  'cond': {
                      '$in': [ '$$cat.position', [ 1, 2 ] ]
                  }
              }
          }
      }
  },
]

pprint.pprint(list(collection.aggregate(pipeline)))

使用
$elemMatch
投影运算符,您可以对数组元素的字段进行筛选(例如,
位置
),但输出将仅显示第一个匹配的数组元素。在已发布的文档中,没有返回两个元素(如position=1或2)的功能。唯一的另一个选项是使用聚合。如果可以使用聚合,我也可以这样做。使用
$elemMatch
投影操作符,您可以对数组元素的字段进行筛选(例如,
位置
),但输出将仅显示第一个匹配的数组元素。在已发布的文档中,没有返回两个元素(如position=1或2)的功能。唯一的另一个选择是使用聚合。如果可以使用聚合,我也可以这样做。