【问题标题】:Pymongo aggregate: filter by count of fields number (dynamic)Pymongo 聚合:按字段数过滤(动态)
【发布时间】:2017-10-09 10:35:30
【问题描述】:

假设我有一个聚合管道,它现在指向一个包含这样构建的文档的集合:

{'name': 'Paul',
 'football_position': 'Keeper',
 'basketball_position': 4,...}

显然,并非每个人都参加每项运动,因此对于某些文档,可能会有不存在的字段。那么关于他们的文件将是

{'name': 'Louis'}

我想要做的是在我的聚合管道中过滤至少参加一项运动的人

我知道使用{'$match': {'football_position': {'$exists': True}}} 很容易检查一个字段,但我想检查这些字段是否存在。

我发现一个老问题有点相似 (Check for existence of multiple fields in MongoDB document),但它会检查 all 字段的存在——虽然很麻烦,但可以通过乘以 $match 操作来实现.另外,也许 mongoDB 现在有比编写自定义 JavaScript 函数更好的方法来处理这个问题。

【问题讨论】:

    标签: python mongodb pymongo


    【解决方案1】:

    也许 mongoDB 现在有更好的方法来处理这个问题

    是的,您现在可以使用聚合运算符 $objectToArray (SERVER-23310) 将键转换为值。它应该能够计算“动态”字段数。将此运算符与$addFields 结合使用可能非常有用。

    这两个运算符都在 MongoDB v3.4.4+ 中可用 以您上面的文件为例:

    db.sports.aggregate([
              { $addFields : 
                 { "numFields" : 
                   { $size:
                     { $objectToArray:"$$ROOT"}
                   }
                 }
              }, 
              { $match: 
                { numFields: 
                  {$gt:2}
                }
              }
    ])
    

    上面的聚合管道,将首先添加一个名为numFields的字段。该值将是数组的大小。该数组将包含文档中的字段数。第二阶段将仅过滤 2 个或更多字段(两个字段,因为仍有 _id 字段加上 name)。

    PyMongo 中,上述聚合管道如下所示:

    cursor = collection.aggregate([
                             {"$addFields":{"numFields":
                                             {"$size":{"$objectToArray":"$$ROOT"}}}}, 
                             {"$match":{"numFields":{"$gt":2}}}
             ])
    

    如上所述,如果您的用例可能,我建议您重新考虑您的data models 以便于访问。即添加一个新字段以在插入/添加新运动位置时跟踪运动数量。

    【讨论】:

    • 太棒了!我不知道这个新运算符,但它确实有用 :) 我不确定我是否可以更改我的数据模型,因为用例与我在此处给出的示例完全不同,但我将再次阅读这部分手动,也许会重新考虑。干杯!
    猜你喜欢
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    相关资源
    最近更新 更多