【问题标题】:How to filter out the documents based on dynamic keys before using $objectToArray?如何在使用 $objectToArray 之前根据动态键过滤掉文档?
【发布时间】:2021-01-13 21:44:35
【问题描述】:

我需要根据动态键进行分组。所以我使用 $objectToArray 来查询动态键。

但我需要根据条件过滤掉文档,以减少进入 $objectToArray 的输入。因为我有数百万个文档,我只想将对象字段的一个子集提供给 $objectToArray 运算符。

我的目标是通过减少传递给 $objectToArray 运算符的数据量来获得更好的查询性能

我的文档结构的示例格式:

[
  {
    "fields": {
      "field_1": {              /* dynamic key */
        "name": "f1",
        "first": {
          "check": true
        }
      },
      "field_2": {             /* dynamic key */
        "name": "f2",
        "second": {
          "check": true
        }
      },
      "description": "abc",
      "summary": {
        "val": "xyz"
      }
    }
  },
  {
    "fields": {
      "field_1": {           /* dynamic key */
        "name": "f1",
        "second": {
          "check": false
        }
      },
      "field_2": null,      /* dynamic key */
      "field_3": {         /* dynamic key */
        "name": "f3",
        "second": {
          "check": true
        },
        "first": {
          "check": true
        }
      },
      "description": "lmn",
      "summary": {
        "val": "abc"
      }
    }
  }
]

我需要根据以下条件过滤掉文档,然后再将其提供给 $objectToArray 运算符:

  1. fields.<*dynamicKey*>.first 存在
  2. fields.<*dynamicKey*>.second 存在

预期输出:

[
  {
    "fields": {
      "field_1": {
        "name": "f1",
        "first": {
          "check": true
        }
      },
      "field_2": {
        "name": "f2",
        "second": {
          "check": true
        }
      }
    }
  },
  {
    "fields": {
      "field_1": {
        "name": "f1",
        "second": {
          "check": false
        }
      },
      "field_3": {
        "name": "f3",
        "second": {
          "check": true
        },
        "first": {
          "check": true
        }
      }
    }
  }
]

如何在不更改文档结构的情况下实现此用例?

db.collection.aggregate([
  {
I need a stage to filter out documents here
  },
  {
    $project: {
      data: {
        $objectToArray: "$fields"
      }
    }
  }

My aggregation query to group based on dynamic keys can be found here:

【问题讨论】:

    标签: mongodb filter mongodb-query aggregation-framework


    【解决方案1】:

    你可以试试,

    • $filter 使用$objectToArray 转换后作为字段数组输入,并使用$type 检查第一个和第二个字段check 类型是否为布尔(布尔)的条件
    • 使用$arrayToObjectfields数组转换为对象
    db.collection.aggregate([
      {
        $project: {
          fields: {
            $arrayToObject: {
              $filter: {
                input: { $objectToArray: "$fields" },
                cond: {
                  $or: [
                    { $eq: [{ $type: "$$this.v.first.check" }, "bool" ] },
                    { $eq: [{ $type: "$$this.v.second.check" }, "bool"] }
                  ]
                }
              }
            }
          }
        }
      }
    ])
    

    Playground

    【讨论】:

    • 感谢您的建议。我的目标是通过过滤掉不需要的字段来获得更好的性能。但是我看不到使用这种方法的任何性能改进。如果有任何其他方法可以过滤掉而不使用像 $objectToArray 这样的重运算符,那就太好了。这样传递给 $objectToArray 的文档数量就更少了。
    猜你喜欢
    • 2018-12-20
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-25
    相关资源
    最近更新 更多