【问题标题】:mongoDB elemMatch ignores other match conditions in the aggregate pipelinemongoDB elemMatch 忽略聚合管道中的其他匹配条件
【发布时间】:2022-01-05 17:22:59
【问题描述】:

我有一个灵活的 mongodb 集合,用于捕获动态工作流字段和优化的值以使用不同的过滤器进行搜索

模型是

{
  "team_id" : String,
  "template_id" : String,
  "meta" : [
    {
        "k" : String,
        "v" : String/Number
    }
  ]
}

对于每个工作流记录,有数百万条记录分布在不同的 team_id 和 template_id 中。一个样本记录集就像

[
  {
    "team_id": "wasp",
    "template_id": "order_booking",
    "document_id": "d1",
    "meta": [
      {
        "k": "assignee",
        "v": "u1"
      },
      {
        "k": "owner",
        "v": "u1"
      },
      {
        "k": "total_amount",
        "v": 1000
      },
      {
        "k": "pincode",
        "v": "560001"
      },
      {
        "k": "state",
        "v": "KA"
      },
    ]
  },
  {
    "team_id": "bee",
    "template_id": "order_booking",
    "document_id": "d900",
    "meta": [
      {
        "k": "assignee",
        "v": "a1"
      },
      {
        "k": "owner",
        "v": "a1"
      },
      {
        "k": "total_amount",
        "v": 19999
      },
      {
        "k": "pincode",
        "v": "560001"
      },
      {
        "k": "state",
        "v": "KA"
      },
    ]
  }
]

我正在考虑使用多个过滤器查询此集合中的数据,例如 Get all records where team is wasp, template is order_booking assignee is u1 with pincode as 10011

上面的查询翻译成

db.getCollection("xyx").aggregate(
    [
        {
            "$match": {
                "team_id": "wasp",
                "template_id": "order_booking",
                "meta": {
                    "$all": [
                        {
                            "$elemMatch": {
                                "k": "assignee",
                                "v": "u1"
                            }
                        },
                        {
                            "$elemMatch": {
                                "k": "pincode",
                                "v": "560001"
                            }
                        }
                    ]

                }
            }
        },
    ]
)

在聚合表达式中使用 elemMatch 的问题是它会扫描集合中的所有文档,而不管最初为 team_idtemplate_id 给出的匹配标准

如何确保初始匹配条件得到遵守,并且 elemMatch 条件仅在该子集中查找?

【问题讨论】:

  • "k": "assingee",有错别字
  • 错字已更正

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

从字面上回答这个问题 - 你可以连续进行 2 场比赛:

db.getCollection("xyx").aggregate(
    [
        {
            "$match": {
                "team_id": "wasp",
                "template_id": "order_booking"
        }, {
            "$match": {
                "meta": {
                    "$all": [
                        {
                            "$elemMatch": {
                                "k": "assignee",
                                "v": "u1"
                            }
                        },
                        {
                            "$elemMatch": {
                                "k": "pincode",
                                "v": "560001"
                            }
                        }
                    ]

                }
            }
        },
    ]
)

第二个 $match 将仅测试通过第一个 $match 的文档。

但是,如果您要优化性能 - 请改为添加复合索引:

{
            "team_id": 1,
            "template_id": 1
}

它将使用内存中的 b-tree 按 team_id 和 template_id 过滤文档,然后仅获取匹配的文档以评估“元”。

【讨论】:

  • 谢谢,我有类似的查询,但问题是索引冲突。在提供索引提示时,问题被排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-25
  • 2020-06-13
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
相关资源
最近更新 更多