我有一个像这样的MongoDB集合:
{
id: "213",
sales : {
'2014-05-23': {
sum: 23
},
'2014-05-22': {
sum: 22
}
}
},
{
id: "299",
sales : {
'2014-05-23': {
sum: 44
},
'2014-05-22': {
sum: 19
}
}
},
我正在寻找一个查询将我的收藏中的所有文件按总和排序(顶部最大金额的文件......)。
对于示例数据,它应该返回如下内容:
{
id: "299",
sales : {
'2014-05-23': {
sum: 44
},
'2014-05-22': {
sum: 19
}
}
},
{
id: "213",
sales : {
'2014-05-23': {
sum: 23
},
'2014-05-22': {
sum: 22
}
}
},
因为:总和44是最大的,因此集合中的此文档首先显示。
这可能(足够快)吗?否则我可以重新设计数据库 - 也许有人对此有建议吗?
答案 0 :(得分:2)
这种表现非常糟糕,因为你正在抛弃你最好的选择,即聚合框架。
你要打破的一个重要规则是“不要将数据用作关键字”。
因此,当您使用实际上是数据点的“键”命名“子文档”时,没有简单的方法来处理它们。一般的MongoDB表示法不喜欢这样,你被迫进行JavaScript评估。与原生方法相比,这仍然是“精神上的”,但确实慢。
更改架构,然后您可以使用聚合框架。以下是改变:
{
"_id": 123,
"sales": [
{ "date": ISODate("2014-05-23T00:00:00Z"), "sum": 23 },
{ "date": ISODate("2014-05-22T00:00:00Z"), "sum": 22 }
]
},
{
"_id": 299,
"sales": [
{ "date": ISODate("2014-05-22T00:00:00Z"), "sum": 19 },
{ "date": ISODate("2014-05-23T00:00:00Z"), "sum": 44 }
]
}
现在你的数据在一个数组中,“路径”是一致的,这意味着你可以很容易地对事物进行排序:
db.collection.find().sort({ "sales.sum": -1 })
因此,具有“最大”“sales.sum”值的文档将是第一个。
如果给出上面的例子,你想用最大的“sales.sum”“排序”内部数组元素,那么你可以使用聚合框架:
db.collection.aggregate([
{ "$unwind": "$sales" },
{ "$sort": { "_id": 1, "sales.sum": -1 } },
{ "$group": {
"_id": "$_id",
"sales": { "$push": "$sales" }
}},
{ "$sort": { "sales.sum": -1 } }
])
使用mapReduce的JavaScript评估可以通过这种方式处理您当前的文档,但不要这样做,因为它会慢得多。