MongoDB使用索引数组

时间:2015-09-25 12:22:40

标签: arrays mongodb

例如,我有一个集合“test”,其数组字段为“numbers”,我有两个文件:

db.test.createIndex({"numbers": 1})
db.test.insert({"title": "A", "numbers": [1,4,9]})
db.test.insert({"title": "B", "numbers": [2,3,7]})

1)如何将所有结果排序为“数字”(使用索引),因此对于数组中的每个值,我得到一个完整的文档?像这样:

 {"_id": "...", "title": "A", "numbers": [1,4,9]}
 {"_id": "...", "title": "B", "numbers": [2,3,7]}
 {"_id": "...", "title": "B", "numbers": [2,3,7]}
 {"_id": "...", "title": "A", "numbers": [1,4,9]}
 {"_id": "...", "title": "B", "numbers": [2,3,7]}
 {"_id": "...", "title": "A", "numbers": [1,4,9]}

2)我怎样才能得到这样的结果(抱歉没有解释,但我认为我在这里想要实现的目标很清楚):

 {"_id": "...", "title": "A", "numbers": 1}
 {"_id": "...", "title": "B", "numbers": 2}
 {"_id": "...", "title": "B", "numbers": 3}
 {"_id": "...", "title": "A", "numbers": 4}
 {"_id": "...", "title": "B", "numbers": 7}
 {"_id": "...", "title": "A", "numbers": 9}

3)我如何获得类似的结果,但是按每个数组中的第二个元素排序?:

 {"_id": "...", "title": "B", "numbers": 3}
 {"_id": "...", "title": "A", "numbers": 4}

此外,我关心性能,所以如果你解释哪种技术更快/更慢(当然,如果有多种方法可以做到这一点),那就太棒了。谢谢。

UPD:让我澄清一下。我们有一个关于“数字”数组的索引。所以我想将这个索引从最小值迭代到最大值并获得当前值所属的文档。因此,某些文档将在结果中呈现N次,其中N =其数组中的元素数(在这种情况下为“数字”)。

1 个答案:

答案 0 :(得分:2)

只需使用按"dot notation"排序的索引:

db.collection.find().sort({ "numbers.0": 1 })

如果现在你想要的位置,这是最快的方法,所以只需使用“索引”(当然从0开始)。所以这同样适用于数组的任何索引位置。

如果您希望对数组中的“最小”值进行排序,则需要执行更多工作,使用.aggregate()来解决此问题:

db.collection.aggregate([
    { "$unwind": "$numbers" },
    { "$group": {
        "_id": "$_id",
        "numbers": { "$push": "$numbers" },
        "min": { "$min": "$numbers" }
    }},
    { "$sort": { "min": 1 } }
])

自然,由于完成的工作比以前的形式需要更多的时间执行。它当然需要$unwind以便将数组元素去规范化为单个文档,而$group具有特定$min来查找最小值。当然,你需要基本的$sort

对于完整的事情,你基本上可以这样做:

  db.test.aggregate([
    { "$project": {
      "title": 1,
      "numbers": 1,
      "copy": "$numbers"
    }},
    { "$unwind": "$copy" },
    { "$group": {
      "_id": {
        "_id": "$_id",
        "number": "$copy"
      },
      "numbers": { "$first": "$numbers" }
    }},
    { "$sort": { "_id.number": 1 } }
  ])

产生:

{ 
  "_id" : { 
    "_id" : ObjectId("560545d64d64216d6de78edb"), 
    "number" : 1
  }, 
  "numbers" : [ 1, 4, 9 ]
}
{ 
  "_id" : { 
    "_id" : ObjectId("560545d74d64216d6de78edc"), 
    "number" : 2
  },
  "numbers" : [ 2, 3, 7 ]
}
{ 
  "_id" : { 
    "_id" : ObjectId("560545d74d64216d6de78edc"), 
    "number" : 3
  }, 
  "numbers" : [ 2, 3, 7 ]
}
{ 
  "_id" : { 
    "_id" : ObjectId("560545d64d64216d6de78edb"),
    "number" : 4
  },
  "numbers" : [ 1, 4, 9 ]
}
{ 
  "_id" : { 
    "_id" : ObjectId("560545d74d64216d6de78edc"),
    "number" : 7
  },
  "numbers" : [ 2, 3, 7 ]
}
{ 
  "_id" : { 
    "_id" : ObjectId("560545d64d64216d6de78edb"),
    "number" : 9
  },
  "numbers" : [ 1, 4, 9 ]
}