“迭代”通过 mongodb 中的所有文档字段

Posted

技术标签:

【中文标题】“迭代”通过 mongodb 中的所有文档字段【英文标题】:"iterate" through all document fields in mongodb 【发布时间】:2021-07-15 07:13:54 【问题描述】:

我有一个包含这种形式的文档的集合:


  "fields_names": ["field1", "field2", "field3"]
  "field1": 1,
  "field2": [1, 2, 3]
  "field3": "12345"

其中 field1、field2、field3 对于每个文档都是“动态的”(我为每个文档都有“fields_names”数组中的字段名称)

我想使用聚合框架测试 2 个文档是否相等。 我使用 $lookup 阶段来获取另一个文档。 我的问题是:如何“迭代”我的收藏的整个字段?

db.collection.aggregate([

  $match: "my_id": "test_id",
  $lookup:
    from: "collection"
    let: my_id: "$my_id", prev_id: "$_id"
    pipeline: [
      $match: "my_id": "$$my_id", "_id": $ne: "$$prev_id"
    ]
    as: "lookup_test"
  
])

在查找的管道中,我想迭代“fields_names”数组以获取字段的名称,然后访问它们的值并在“原始文档”(不是 $lookup)和其他文档($lookup 文档)。 或者:只是迭代所有字段(不包括“fields_names”数组)

我想用所有具有相同字段值的文档填充“lookup_test”数组..

【问题讨论】:

请根据您的示例文档添加您的预期结果。 【参考方案1】:

您必须比较文档的两个“部分”部分,这意味着您必须(对于每个文档)在 $lookup 中执行此操作,不用说这将是一个非常昂贵的管道.话虽如此,这就是我的做法:

db.collection.aggregate([
  
    $match: 
      "my_id": "test_id"
    
  ,
  
    "$lookup": 
      "from": "collection",
      "let": 
        id: "$_id",
        partialRoot: 
          $filter: 
            input: 
              "$objectToArray": "$$ROOT"
            ,
            as: "fieldObj",
            cond: 
              "$setIsSubset": [
                [
                  "$$fieldObj.k"
                ],
                "$fields_names"
              ]
            
          
        
      ,
      pipeline: [
        
          $match: 
            $expr: 
              $and: [
                
                  $ne: [
                    "$$id",
                    "$_id"
                  ]
                ,
                
                  $eq: [
                    
                      $size: "$$partialRoot"
                    ,
                    
                      $size: 
                        "$setIntersection": [
                          "$$partialRoot",
                          
                            $filter: 
                              input: 
                                "$objectToArray": "$$ROOT"
                              ,
                              as: "fieldObj",
                              cond: 
                                "$setIsSubset": [
                                  [
                                    "$$fieldObj.k"
                                  ],
                                  "$fields_names"
                                ]
                              
                            
                          
                        ]
                      
                    
                  ]
                
              ]
            
          
        ,
        
      ],
      "as": "x"
    
  
])

Mongo Playground

如果您可以通过代码动态构建查询,您可以通过在$lookup 阶段使用相同的匹配查询来提高效率,如下所示:

const query =  my_id: "test_id" ;

db.collection.aggregate([
   
      $match: query
   ,
   
      $lookup: 
         ...
         pipeline: [
              $match: query ,
              ... rest of pipeline ...
         ]
      
   
])

这样你只匹配至少匹配初始查询的文档,这应该会大大提高查询性能(显然取决于字段 x 值熵)

另外需要注意的是,如果 x 文档匹配,您将获得 x 次相同的结果,这意味着您可能希望将 $limit: 1 阶段添加到您的管道中。


【讨论】:

以上是关于“迭代”通过 mongodb 中的所有文档字段的主要内容,如果未能解决你的问题,请参考以下文章

mongoDB_08索引的操作

Mongodb Lookup 无法正常工作

使用同一文档中的字段减少mongodb中的字段

Python + MongoDB - 光标迭代太慢 - 未解决?

如何为 MongoDB 集合中的所有文档选择单个字段?

为集合中的所有文档更新数组中的一个或两个字段 - mongodb