MongoDB根据查询语法对未使用的子文档进行索引

时间:2016-04-29 14:58:15

标签: mongodb indexing subdocument

我使用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中,这两个符号是等价的,而且坦率地说,我希望数据库足够智能,以确定这两个查询术语指的是同一个字段并使用适当的索引。 / p>

我对索引整个子文档的解决方法的关注是,最终,该子文档可能包含更多我不需要编入索引的字段,并且浪费时间和RAM保存索引术语似乎不是最理想的。需要。

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

1 个答案:

答案 0 :(得分:1)

我想我在查看mongo文件后想出来了。基本上, 这两者之间的语义差异。基本上,在查询{c: {d: d1}}的第一种形式中,mongo假定您正在指定整个子文档。因此,如果您有一个子文档{c: {d: d1, e: e1}},它就不会匹配。

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

这种差异扩展到索引。 _ensureIndex({c: 1})_ensureIndex({'c.d': 1})是两个不同的索引,即使第一个索引整个子文档,如果使用c.d表示法查询单个字段,也不会使用它