如何在mongodb中索引以下查询?

时间:2013-03-06 16:27:44

标签: mongodb indexing

我试图找出mongodb中使用的最佳索引:

db.articles.find({"images.url":{"$exists":true}, \  
    "source_id": {"$in":[ObjectId("511baf3aa56bde8e94000002"), ObjectId("511baf3aa56bde8e94000999")]}})  \
    .sort({"published_at": -1})

我只想包含images.url存在的文章,所以我想知道它是否是一个稀疏索引?并且不确定要按顺序索引哪些字段,因为我已经阅读了不同的指针:

  1. 首先,您将在其中查询确切值的字段。 (“images.url”:存在)
  2. 其次,您要排序的字段。 (:published_at)
  3. 最后,您将在其中查询一系列值的字段。 (SOURCE_ID)
  4. 另外,在上面的例子中,我不确定source_id是否是一系列值?

    我在想:

    index "images.url": -1, published_at: -1, source_id: 1, {sparse: true}
    

    但是我对于索引的最大化排他性也很不满,所以我在考虑:

    index source_id: 1, "images.url": -1, published_at: -1, {sparse: true}
    

1 个答案:

答案 0 :(得分:4)

如果我们有这样的集合

{ a:1, b:1, c:1 }
{ a:1, b:1, c:2 }
{ a:1, b:1, c:3 }
{ a:1, b:2, c:1 }
... // all permutations up to:
{ a:3, b:3, c:3 }

以随机顺序设想这个集合

这是({a:1,b:1,c:1})的复合指数看起来像

a:  |        1        |        2        |        3        |
    |-----------------+-----------------+-----------------|                   
b:  |  1  |  2  |  3  |  1  |  2  |  3  |  1  |  2  |  3  |
    |-----+-----+-----+-----+-----+-----+-----+-----+-----|
c:  |1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|1|2|3|

对于每一个你拥有它的所有b的所有c依次,好吗?

对于查询: db.xx.find({a:2})。sort({b:1}),您可以看到b元素在a =下面的顺序2;索引将用于排序 - explain()中的“scanAndOrder”:false 。如果您的查询是 db.xx.find({a:2,c:{$ in:[1,3]}}),则会发生同样的情况。排序({b:1}) < / p>

但是这个: db.xx.find({a:{$ in:[1,3]}})。sort({b:1})。explain()会告诉你“scanAndOrder”:true ,这意味着索引不用于排序(虽然它用于查询) - 从上面的模式可以看出,“b”不是按顺序排列的对于a = [1,3]。

这就是为什么索引的有效序列是:

(1) exact matches (only one!)
(2) sort criteria
(3) matches that point to more than one document

在你的情况下,没有完全匹配;两个查询都返回多个文档。让我们在我们的例子中试试这个:

<强> db.xx.find({一个:{$中:[1,3]},B:{$中:[1,3]}})排序({C:1})。。 explain():使用索引进行查询,但不进行排序,它会扫描15并返回12个对象。

<强> db.xx.find({B:{$中:[1,3]},C:{$中:[1,3]}})排序({一个:1})。。 explain():使用索引进行查询和排序,但扫描21并返回12个对象。

哪一个更好?这取决于您的使用案例。如果您的查找通常会返回许多文档,那么使用索引可以更有效地使用索引 - 但如果它通常只返回少数(在众多中),那么您可能更喜欢更有效的扫描。尝试一下,看看使用explain()

有什么好处

这有帮助吗?

问候

罗纳德

P.S。我用它来创建示例集合:

[1,2,3].forEach(function(a){
    [1,2,3].forEach(function(b){
        [1,2,3].forEach(function(c){
            db.xx.insert({a:a,b:b,c:c});
        })
    })
})