【问题标题】:Using index to sort documents in Mongo aggregation query在 Mongo 聚合查询中使用索引对文档进行排序
【发布时间】:2019-11-19 22:55:33
【问题描述】:

我想在表格中显示我的文档(就像网页中的历史记录),所以我有几个搜索条件。 这是我的文档结构:

{
  "_id": "5dcae9defbb1bf46e9162641",
  "idUnykoo": 1,
  "workflowData": [
    {
      "created": "2018-12-26T16:55:39Z[UTC]",
      "login": "AppMov",
      "type": "CONSULTA_SIC",
      "consultaSIC": {
        "id": "1",
        "status": "SUCCESS",
        "consultaBC": {
          "created": "Nov 26, 2015 4:55:39 PM",
          "user": {
            "id": 1001,
            "login": "AppMov",
            "apellidoPaterno": "marchand",
            "apellidoMaterno": "sand",
            "primerNombre": "alex",
            "email": "alex@toto.com"
          }
        }
      }
    },
    {
      "created": "2019-11-12T17:20:15.870Z[UTC]",
      "login": "AppMov",
      "type": "SMS",
      "vprData": {
        "name": "VPR ALEX",
        "dataId": "297065",
        "connectorVprId": "1",
        "data": [
          {
            "dataIndex": 1,
            "name": "Edad",
            "value": "59"
          }
        ]
      }
    }
  ]
}

workflowData 数组的每个元素都是用户的一个动作,我想在历史记录中显示某种类型的所有动作。

我希望能够通过/和过滤我的文档: workflowData.type workflowData.login workflowData.created

我希望我的结果在workflowData.created上按降序排序

我正在尝试做这个查询:

db.workfloos.aggregate([{$match:{'workflowData':{$elemMatch:{'type':'CONSULTA_SIC','created':{$gte:'2018-11-26T16:55:39Z[UTC]'},'login':'alex'}}}},{$sort:{'workflowData.created':-1}},{'$limit':500}])

但它真的很慢,即使我在这些键上放置了一个多键索引:

    "key" : {
            "idUnykoo" : -1,
            "workflowData.type" : 1,
            "workflowData.created" : 1,
            "workflowData.login" : 1
        }

有人可以帮助我了解是否有一种方法可以在 mongo db 中以合理的响应时间执行此操作吗?我有近一百万个文档,我可以看到排序非常慢,因为它似乎无法利用索引让文档在匹配后已经排序。所以它会尝试对匹配的所有结果进行排序。

谢谢

【问题讨论】:

  • 注意几点:(1)查询可能没有正确使用索引(因此很慢);这是因为无法应用与查询一起使用的索引前缀。索引定义中的idUnykoo : -1 不允许在查询中使用索引。 (2)你说的数据量很大,多键索引可以创建更大的索引;有时,由于大小的原因,将索引加载到内存中会变得很困难。我建议在您的查询中运行 explain() 并将结果包含在帖子中;这将显示索引是否被正确使用。

标签: mongodb sorting indexing mongodb-query aggregation-framework


【解决方案1】:

在以下字段上创建索引:

db.collectionName.createIndex({"workflowData.created":-1})
db.collectionName.createIndex({"workflowData.type":1, "workflowData.created":-1})

我认为集合上的这些索引将适当地处理您的聚合查询:

db.workfloos.aggregate([{$match:{'workflowData':{$elemMatch:{'type':'CONSULTA_SIC','created':{$gte:'2018-11-26T16:55:39Z[UTC]'},'login':'alex'}}}},{$sort:{'workflowData.created':-1}},{'$limit':500}])

详情请访问MongoDB官方文档Aggregation Pipeline Optimization

特别是查看$sort Operator and Performance

【讨论】:

  • 感谢克里希纳的回答。我试过了,但不幸的是,这并不能解决我的问题,查询需要 20 多秒才能运行。即使没有关于“登录”的条款,它也很慢。我将使用 explain() 输出更新我的帖子。
  • 好吧,我似乎无法编辑我的问题,也无法在评​​论中发布所有的 explain() 输出,因为它太长了。所以基本上我的获胜计划是: "inputStage" : {"stage" : "IXSCAN" ... "indexBounds" : {"workflowData.type" : ["[\"CONSULTA_SIC\",\"CONSULTA_SIC\"]"] , "workflowData.created" : [ "({}, \"2018-11-26T16:55:39Z[UTC]\"]" ] } 然后我在相同的字段上得到了一个带有 $elemMatch 的过滤阶段.. .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多