【问题标题】:Can the same MongoDB document show up more than once in a single cursor using a mulitkey index?同一个 MongoDB 文档可以使用多键索引在单个游标中多次显示吗?
【发布时间】:2013-11-06 00:02:15
【问题描述】:

我正在考虑将时间序列数据捆绑到会话文档中。在每个会话中,都会有一系列事件。每个事件都有一个时间戳。我知道我可以在这些事件的时间戳上创建一个多键索引,但我很好奇 MongoDB 使用什么机制来防止同一文档在一个查询中出现两次。

为了澄清,想象一下包含以下文档的会话集合:

{
  _id: 'A',
  events: [
    {time: '10:00'},
    {time: '15:00'}
  ]
}
{
  _id: 'B',
  events: [
    {time: '12:00'}
  ]
}

如果我用db.sessions.ensureIndex({'events.time' : 1}) 添加一个多键索引,我希望该索引的 b 树看起来像这样:

'10:00' => 'A'
'12:00' => 'B'
'15:00' => 'A'

如果我使用{'events.time': {$gte: '10:00'}} 查询集合,MongoDB 会扫描 b-tree 并返回:

{ "_id" : "A", "events" : [  {  "time" : "10:00" },  {  "time" : "15:00" } ] }
{ "_id" : "B", "events" : [  {  "time" : "12:00" } ] }

Mongo 如何防止文档A 第二次显示为光标中的第三个结果?对于小型索引扫描,它可以只跟踪已经查看过哪些文档,但是如果索引很大,会发生什么?是否有过同一个文档在单个光标中出现多次的情况?

我的假设是它不会。 Mongo 可以查看它正在扫描的文档,并通过检查索引数组中较早的条目来检测它已经在扫描中较早地匹配。但是,我在 MongoDB 文档中找不到任何提及此行为的内容,因此真正了解会发生什么很重要。

(注意:我确实知道如果在扫描光标时修改了文档,则文档可能会多次出现在单个查询中。这不应该构成查询从不编辑时间戳的时间序列数据的问题。即使在扫描期间将新事件添加到会话中,如果 Mongo 使用类似于我上面提到的检测机制,它应该能够省略移动的文档来自查询结果。)

【问题讨论】:

  • 有趣的问题,但是如果索引大小很大,那么查询优化器将更喜欢集合扫描(BasicCursor),因为它的 nscanned 会更低。
  • 不一定。我可能只扫描 1 个月的数据,其中可能包含大量会话,但仍远少于集合中的总会话数。在这种情况下,您肯定希望 Mongo 使用索引。

标签: mongodb multikey


【解决方案1】:

我在 MongoDB 中找不到任何提及此行为的内容 文档,重要的是要真正知道会发生什么。

文档中很少提到实现的内部,毕竟你描述的是预期的行为。

有代码to deduplicate a result setthere are tests 以确保其正常工作。毕竟,多键索引不是此类功能的主要用例 - 如果您的查询中有 $or clause,则还必须对结果进行重复数据删除。

【讨论】:

  • 哦,是的!我什至没有想过 $or 子句扫描两个不同索引的情况。所以看起来像一组无序的访问磁盘位置在游标的生命周期内被保留。这是否意味着如果在扫描期间调整文档大小,文档可能会再次显示?这可能会使在将一堆会话处理成报告时添加新事件变得不安全。
  • 是的,如果文档移动,那么它可能会显示两次 - 除非您正在遍历索引,在这种情况下您不会再次遇到它。将一堆东西整理成报告通常是“过去”的数据——所以“现在”的变化不应该影响它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 2016-03-15
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多