【问题标题】:"iterate" through all document fields in mongodb“迭代”通过 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”数组..

【问题讨论】:

  • 请根据您的示例文档添加您的预期结果。

标签: mongodb aggregation-framework aggregate aggregation


【解决方案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 阶段添加到您的管道中。


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-11
    • 2012-03-18
    • 2022-12-04
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多