首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MongoDB聚合查询优化:匹配->解带->匹配与取消->匹配

MongoDB聚合查询优化:匹配->解带->匹配与取消->匹配
EN

Stack Overflow用户
提问于 2020-04-23 07:26:21
回答 1查看 1.1K关注 0票数 0

输入数据

代码语言:javascript
复制
{
    "_id" : ObjectId("5dc7ac6e720a2772c7b76671"),
    "idList" : [ 
        {
            "queueUpdateTimeStamp" : "2019-12-12T07:16:47.577Z",
            "displayId" : "H14",
            "currentQueue" : "10",
            "isRejected" : true,
            "isDispacthed" : true
        },
        {
            "queueUpdateTimeStamp" : "2019-12-12T07:16:47.577Z",
            "displayId" : "H14",
            "currentQueue" : "10",
            "isRejected" : true,
            "isDispacthed" : false
        }
    ],
    "poDetailsId" : ObjectId("5dc7ac15720a2772c7b7666f"),
    "processtype" : 1
}

输出数据

代码语言:javascript
复制
{
    "_id" : ObjectId("5dc7ac6e720a2772c7b76671"),
    "idList":
     {
            "queueUpdateTimeStamp" : "2019-12-12T07:16:47.577Z",
            "displayId" : "H14",
            "currentQueue" : "10",
            "isRejected" : true,
            "isDispacthed" : true
    },
    "poDetailsId" : ObjectId("5dc7ac15720a2772c7b7666f"),
    "processtype" : 1
}

unwind查询1 ( )

代码语言:javascript
复制
     aggregate([
     {
         $unwind: { path: "$idList" }
     },
     {
         $match: { 'idList.isDispacthed': isDispatched }
     }
     ])

match查询2 ( 然后 unwind 然后 match**)** )

代码语言:javascript
复制
     aggregate([
     {
         $match: { 'idList.isDispacthed': isDispatched }
     },
     {
         $unwind: { path: "$idList" }
     },
     {
         $match: { 'idList.isDispacthed': isDispatched }
     }
     ])

我的问题/我的关切

(假设这个集合中有大量的文档(50k +),并且假设在这个查询之后在同一个管道中有其他的查找和投影)

match -> unwind -> matchunwind ->match

  1. 这两个查询之间有什么性能差异吗?
  2. 还有其他(更好的)方法来编写这个查询吗?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-23 08:06:40

这都取决于MongoDB查询计划优化器:

聚合管道操作有一个优化阶段,它试图重塑管道以提高性能。 要了解优化器如何转换特定的聚合管道,请将解释选项包含在db.collection.aggregate()方法中。

https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/

poDetailsId创建索引并运行以下查询:

代码语言:javascript
复制
db.getCollection('collection').explain().aggregate([
     {
         $unwind: "$idList"
     },
      {
         $match: { 
           'idList.isDispacthed': true, 
           "poDetailsId" : ObjectId("5dc7ac15720a2772c7b7666f") 
         }
     }  
])
代码语言:javascript
复制
{
    "stages" : [ 
        {
            "$cursor" : {
                "query" : {
                    "poDetailsId" : {
                        "$eq" : ObjectId("5dc7ac15720a2772c7b7666f")
                    }
                },
                "queryPlanner" : {
                    "plannerVersion" : 1,
                    "namespace" : "test.collection",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "poDetailsId" : {
                            "$eq" : ObjectId("5dc7ac15720a2772c7b7666f")
                        }
                    },
                    "queryHash" : "2CF7E390",
                    "planCacheKey" : "A8739F51",
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "poDetailsId" : 1.0
                            },
                            "indexName" : "poDetailsId_1",
                            "isMultiKey" : false,
                            "multiKeyPaths" : {
                                "poDetailsId" : []
                            },
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 2,
                            "direction" : "forward",
                            "indexBounds" : {
                                "poDetailsId" : [ 
                                    "[ObjectId('5dc7ac15720a2772c7b7666f'), ObjectId('5dc7ac15720a2772c7b7666f')]"
                                ]
                            }
                        }
                    },
                    "rejectedPlans" : []
                }
            }
        }, 
        {
            "$unwind" : {
                "path" : "$idList"
            }
        }, 
        {
            "$match" : {
                "idList.isDispacthed" : {
                    "$eq" : true
                }
            }
        }
    ],
    "ok" : 1.0
}

正如您所看到的,MongoDB将将此聚合更改为:

代码语言:javascript
复制
db.getCollection('collection').aggregate([
     {
         $match: { "poDetailsId" : ObjectId("5dc7ac15720a2772c7b7666f") }
     }
     {
         $unwind: "$idList"
     },
     {
         $match: { 'idList.isDispacthed': true }
     }  
])

从逻辑上讲,$match -> $unwind -> $match更好,因为您筛选(按索引)记录的子集,而不是全扫描(处理100个匹配的文档≠all documents)。

如果聚合操作只需要集合中的数据子集,则使用$match$limit$skip阶段来限制在管道开始时输入的文档。当放置在管道的开头时,$match操作使用适当的索引只扫描集合中的匹配文档。

https://docs.mongodb.com/manual/core/aggregation-pipeline/#early-filtering

一旦您操作了文档,MongoDB就无法应用索引。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61381569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档