【问题标题】:Mongodb querying - How to specify index traversal order?Mongodb查询 - 如何指定索引遍历顺序?
【发布时间】:2020-12-22 04:56:10
【问题描述】:

上下文

我有一个 users 集合,其中包含一组键值对,如下所示:

{
  name: 'David',
  customFields: [
    { key: 'position', value: 'manager' },
    { key: 'department', value: 'HR' }
  ]
},

{
  name: 'Allison',
  customFields: [
    { key: 'position', value: 'employee' },
    { key: 'department', value: 'IT' }
  ]
}

customFields 中的字段名称可由应用程序用户配置,因此为了使其可索引,我将它们存储为键值对数组。索引{ 'customFields.key': 1, 'customFields.value': 1} 工作得很好。问题是当我想以任一顺序(升序或降序)检索结果时。假设我想按任意顺序对具有自定义字段 position 的所有用户进行排序。下面的查询给了我升序:

db.users.find({ customFields: { $elemMatch: { key: 'position' } } })

但是,我不知道如何得到相反的顺序。我很确定索引的结构方式,如果我可以告诉 mongodb 向后遍历索引,我会得到我想要的。另一种选择是使用另外 2 个索引来覆盖两个方向,但成本更高。

有没有办法指定遍历方向?如果没有,有什么好的选择?非常感谢。

编辑

我想进一步澄清我的情况。我试过了:

db.users.find({ customFields: { $elemMatch: { key: 'position' } } })
  .sort({ 'customFields.key': 1, 'customFields.value': 1 })

db.users.find({ customFields: { $elemMatch: { key: 'position' } } })
  .sort({'customFields.value': 1 })

这两个查询仅对过滤后的文档进行排序,这意味着排序将应用于它们拥有的所有自定义字段,而不是与查询匹配的字段(在本例中为position )。因此,使用sort 方法似乎没有任何帮助。

不使用任何排序可以方便地以正确的升序顺序返回文档。从解释结果中可以看出:

"direction" : "forward",
"indexBounds" : {
  "customFields.key" : [
    "[\"position\", \"position\"]"
  ],
  "customFields.value" : [
    "[MinKey, MaxKey]"
   ]
 }

我对@9​​87654331@ 使用完全匹配,所以我不在乎它的顺序。在customFields.key的每个值中,customFields.value的值都是按照索引中指定的顺序排列的,所以我就照原样取出来就好了。现在,如果我可以这样做:

db.users.find({ customFields: { $elemMatch: { key: 'position' } } })
  .direction('backwards')

这相当于使用索引{ 'customFields.key': -1, 'customFields.value': -1 }。就像我说的,我不在乎customFields.key 的订单,而'customFields.value': -1 正是我想要的。我搜索了 mongodb 文档,但找不到类似的东西。

我可以检索与customFields.key 匹配的所有文档并自己进行排序,但它的成本很高,因为文档的数量可能会变得非常大。理想情况下,所有的过滤和排序都由索引来解决。

【问题讨论】:

  • 你已按升序创建索引,按降序创建索引{ 'customFields.key': -1, 'customFields.value': -1}

标签: mongodb sorting indexing


【解决方案1】:

这是您创建的复合索引:

db.users.createIndex( { "customFields.key": 1, "customFields.value": 1 } )

此索引将允许使用两个字段按升序遍历:

db.users.sort( { "customFields.key": 1, "customFields.value": 1 } )

或者,它还可以支持以降序顺序使用两个键进行遍历:

db.users.sort( { "customFields.key": -1, "customFields.value": -1 } )

如果您需要混合行为,即在一个字段上上升但在另一个字段上下降,那么您需要添加第二个索引:

db.users.createIndex( { "customFields.key": 1, "customFields.value": -1 } )

请注意,添加第二个索引后,现在支持所有四种可能的组合。

【讨论】:

  • 嗨蒂姆,感谢您的回答。我已经编辑了我的问题以更详细地解释我的问题。
猜你喜欢
  • 1970-01-01
  • 2018-09-04
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-19
  • 2013-09-02
  • 2020-07-16
相关资源
最近更新 更多