2

我将 Meteor 与 MongoDB 一起使用,其中包含如下文档集合:

{a: 'a1',
 b: 'b1',
 c: {
     d: 'd1',
     e: 'e1'
    }
}

我最初创建了一个这样的索引: collection._ensureIndex({'c.d': 1});

并运行这样的查询: collection.find({c: {d: 'd1'}). 这些运行非常缓慢,当我使用 explain() 进行调试时,我意识到它们没有使用索引。

OTOH,如果我运行这样的查询: collection.find({'c.d': 'd1'}),那么 Mongo使用索引。

我现在已更改索引以索引整个子文档,即collection._ensureIndex({c: 1}),第一个查询现在命中索引。

我的问题是,这是一个错误还是一个功能?我的印象是,在 JSON 中,这两种表示法是等价的,坦率地说,我希望数据库足够聪明,能够判断出这两个查询词指的是同一个字段并使用适当的索引。

我对索引整个子文档的解决方法的担忧是,最终,该子文档可能包含更多我不需要索引的字段,而且浪费时间和 RAM 保存我不需要的索引项似乎不是最佳选择。

如果这不是错误,有没有办法让 Mongo 识别嵌套对象语法并正确使用索引?

4

1 回答 1

1

我想我是在检查了 mongo 文件后才知道的。基本上,这两者之间的语义存在差异。本质上,在 query 的第一种形式中{c: {d: d1}},mongo 假定您正在指定整个子文档。因此,如果您有 subdocument {c: {d: d1, e: e1}},它将不匹配。

OTOH,查询的第二种形式{'c.d': d1}意味着您只在子文档中的一个字段上指定匹配项。即使子文档具有其他字段或整个子子文档,这也会匹配。

这种差异延伸到指数。_ensureIndex({c: 1})and_ensureIndex({'c.d': 1})是两个不同的索引,即使第一个索引整个子文档,如果您使用c.d符号查询单个字段,它也不会被使用。

于 2016-05-17T03:55:08.800 回答