在MongoDB中,您可以索引字段以查找数组中没有值的对象吗?

时间:2012-02-21 22:54:29

标签: mongodb

我知道Multikeys允许您高效地查找将数组作为字段的对象,其中该数组中存在特定值。

例如,您可以存储一个对象:

{
  "ar":["book","cat"]
}

然后,如果索引“ar”字段,您可以说:

db.blah.find({"ar":"cat"})

它将有效地找到上述对象。

然而,像这样的工作:

db.blah.find({"ar":{$not : "cat"}})

在这里,我想找到“ar”数组包含“cat”的所有对象。这个查询是否有效,如果有效,它会有效吗? (即它会使用“ar”字段上的索引吗?)

2 个答案:

答案 0 :(得分:1)

如果您查看此MongoDB server issue,答案是“它可以使用索引”。

但是,使用$not运算符时,使用索引通常效率不高。如果2%的条目中出现'cat',那么您仍然需要阅读98%的数据。此时,您也可以一次只读取一个条目的整个数据集。

答案 1 :(得分:1)

$ not运算符不会以您暗示的方式使用,它是一个元运算符,用于否定仅对另一个运算符的检查。我认为你的意思是使用$ ne:

db.blah.find({ "ar" : { $ne : "cat"}})

如果你这样做并且你有一个“ar”的索引,那么因为它是一个负面的匹配,你将不得不扫描索引中的所有文件来检查每一个 - 这实际上是效率低于单独扫描表,因为你必须进行索引加载/扫描,然后拉出所有数据以返回结果。

如果这足够重要且经常足以避免这种情况发生,那么为什么不添加一个真/假的简单字段(或者在我的例子中为0/1)来测试“cat”字段是否存在。在这里,我将这样一个字段添加到现有数据集中,我建议将其添加到创建或修改中以便在将来添加“cat” - 避免批处理操作通常是一个好主意:

db.blah.update({ "ar" : "cat"}, { $set : {"cat_test" : 1 } }, true, true)
db.blah.update({ "ar" : {$ne : "cat"}}, { $set : {"cat_test" : 0 } }, true, true)
db.blah.ensureIndex({ "cat_test" : 1 })

现在你可以运行类似的东西:

db.blah.find({ "cat_test" : 0 })

这将有效地使用索引。这是否值得,取决于您的数据使用情况和您的模型,当然