就MongoDB的性能而言,进行多计数的最佳选择?

时间:2019-06-17 13:11:38

标签: mongodb performance count aggregation-framework

我必须在MongoDB中进行多次计数。我有这样的文档集合(大约150万个):

reportDocument
{
  _id : Guid,
  status : number (enum value),
  name : string
}

具有自定义索引

{
    name : 1,
    status : 1
}

我的目标是按这样的名称获得一个计数器

{
    inProgress : 3,
    completed : 2,
    canceled : 4
}

我有两种解决方法。第一个只是简单地使用count 3次

db.reports.count({name : "name", status : 2}) // for canceled, completed etc

并根据这些值形成计数器。此查询使用索引,并且应该可以快速运行,但是我必须从客户端发出3个请求。第二种选择是使用聚合框架。我有两个变体。

第一个

解释告诉我这是一个collscan,我认为这很糟糕,所以我将其修改为第二个

db.reports.aggregate([
  { "$facet": {
    "inProgress": [
      { "$match" : {"name": "name", status : 0}},
      { "$count": "count" },
    ],
    "completed": [
      { "$match" : {"name": "name", status : 1}},
      { "$count": "count" },
    ],
    "canceled": [
      { "$match" : { "name": "name2", status : 2}},
      { "$count": "count" },
    ]
  }},

  { "$project": {
    "inProgress": { "$arrayElemAt": ["$inProgress.count", 0] },
    "completed": { "$arrayElemAt": ["$completed.count", 0] },
    "canceled": { "$arrayElemAt": ["$canceled.count", 0] }
  }}
])

第二

此查询在$ match阶段使用索引,但是据我了解,聚合框架仅在从游标检索文档后才进行聚合,因此它将获取所有匹配的{ name : "name" }文档并遍历所有这些文档而无需获取考虑到我的自定义索引(还包括有关状态的信息),对我来说听起来并不有效。

db.reports.aggregate([
  {"$match" : {"name": "name"}},
  { "$facet": {
    "inProgress": [
      { "$match" : { status : 0 }},
      { "$count": "count" },
    ],
    "completed": [
      { "$match" : { status : 1}},
      { "$count": "count" },
    ],
    "canceled": [
      { "$match" : { status : 2}},
      { "$count": "count" },
    ]
  }},

  { "$project": {
    "inProgress": { "$arrayElemAt": ["$inProgress.count", 0] },
    "completed": { "$arrayElemAt": ["$completed.count", 0] },
    "canceled": { "$arrayElemAt": ["$canceled.count", 0] }
  }}
])

我无法在这些解决方案之间做出选择,也许还有其他解决方案。我想要一个查询,它可以充分利用我的自定义索引(其中包括有关状态的信息,似乎聚合没有使用它),并且执行速度与3个独立计数查询一样快。那么实现我的目标的最佳实践是什么?

0 个答案:

没有答案
相关问题