MongoDB基于每月组

时间:2018-02-21 07:34:32

标签: mongodb

这是我到目前为止在聚合查询

上尝试的内容
db.getCollection('storage').aggregate([
  {
    "$match":  {
      "user_id":  2
    }
  },
  {
    "$project":  {
      "formattedDate":  {
        "$dateToString":  { "format":  "%Y-%m", "date":  "$created_on" }
      },
      "size":  "$size"
    }
  },
  { "$group":  {
    "_id"  :  "$formattedDate",
    "size" :  { "$sum":  "$size" }
  } }
])

这是结果

/* 1 */
{
    "_id" : "2018-02",
    "size" : NumberLong(10860595386)
}

/* 2 */
{
    "_id" : "2017-12",
    "size" : NumberLong(524288)
}

/* 3 */
{
    "_id" : "2018-01",
    "size" : NumberLong(21587971)
}

这是文档结构

{
    "_id" : ObjectId("5a59efedd006b9036159e708"),
    "user_id" : NumberLong(2),
    "is_transferred" : false,
    "is_active" : false,
    "process_id" : NumberLong(0),
    "ratio" : 0.000125759169459343,
    "type_id" : 201,
    "size" : NumberLong(1687911),
    "is_processed" : false,
    "created_on" : ISODate("2018-01-13T11:39:25.000Z"),
    "processed_on" : ISODate("1970-01-01T00:00:00.000Z")
}

最后,解释结果:

/* 1 */
{
    "stages" : [ 
        {
            "$cursor" : {
                "query" : {
                    "user_id" : 2.0
                },
                "fields" : {
                    "created_on" : 1,
                    "size" : 1,
                    "_id" : 1
                },
                "queryPlanner" : {
                    "plannerVersion" : 1,
                    "namespace" : "data.storage",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "user_id" : {
                            "$eq" : 2.0
                        }
                    },
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "user_id" : 1
                            },
                            "indexName" : "user_id",
                            "isMultiKey" : false,
                            "multiKeyPaths" : {
                                "user_id" : []
                            },
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 2,
                            "direction" : "forward",
                            "indexBounds" : {
                                "user_id" : [ 
                                    "[2.0, 2.0]"
                                ]
                            }
                        }
                    },
                    "rejectedPlans" : []
                }
            }
        }, 
        {
            "$project" : {
                "_id" : true,
                "formattedDate" : {
                    "$dateToString" : {
                        "format" : "%Y-%m",
                        "date" : "$created_on"
                    }
                },
                "size" : "$size"
            }
        }, 
        {
            "$group" : {
                "_id" : "$formattedDate",
                "size" : {
                    "$sum" : "$size"
                }
            }
        }
    ],
    "ok" : 1.0
}

问题

我可以在0,002sec中几乎立即导航并获得所有结果。但是,当我指定user_id并通过每个月的分组对它们求和时,我的结果介于0,300s到0,560s之间。我在一个请求中执行类似的任务,并且完成时间超过一秒钟。

到目前为止我尝试了什么:

  • 我已为user_id
  • 添加了索引
  • 我已为created_on
  • 添加了索引
  • 我使用了更多$match个条件。但是,这更糟糕

此系列目前有近200,000份文件,其中约有150,000份属于user_id = 2

如何最小化此查询的响应时间?

注意:使用了MongoDB 3.4.10。

1 个答案:

答案 0 :(得分:0)

Pratha,

尝试在“created_on”和“size”字段上添加sort作为聚合管道中的第一个阶段。

db.getCollection('storage').aggregate([
  {
    "$sort":  {
      "created_on":  1, "size": 1
    }
  }, ....

在此之前,添加复合键索引: 。db.getCollection( '存储装置')的createIndex({created_on:1,尺寸:1})

如果您在$ group阶段之前对数据进行排序,则会提高总计积累的效率。

关于排序聚合阶段的注意事项:

$ sort阶段的RAM限制为100兆字节。默认情况下,如果阶段超出此限制,$ sort将产生错误。要允许处理大型数据集,请将allowDiskUse选项设置为true以启用$ sort操作以写入临时文件。

P.S

通过userID摆脱匹配阶段以测试性能,或者也将userID添加到复合键。