问题
I have a MongoDB collection like this:
{
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
}
}
},
I'm looking for a query to get all documents in my collection sorted by sum (document with the largest sum on top...).
For the example data it should return something like this:
{
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
}
}
},
Because: the sum 44 is the largest, therefore this document in the collection shows first.
Is that possibly (and fast enough)? Else I can redesign the database - maybe someone has a suggestion for that?
回答1:
The performance of this is terrible, and because you are throwing away your best option, which is the aggregation framework.
The big rule you are breaking here is "Don't use data as keys".
So when you name "sub-documents" with "keys" that are actually data points then there is no easy way to process them. General MongoDB notation does not like this and you are forced in to JavaScript evaluation. This is still "spritely", but really slow by comparison to native methods.
Change your schema, and then you can use the aggregation framework. Here is the change first:
{
"_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 }
]
}
Now your data is in an array and the "paths" are consistent, this means you can sort things very easily:
db.collection.find().sort({ "sales.sum": -1 })
So the document with the "largest" "sales.sum" value will be first.
If then given the above example, you wanted to "sort" the inner array elements by the largest "sales.sum" as well, then you can use the aggregation framework:
db.collection.aggregate([
{ "$unwind": "$sales" },
{ "$sort": { "_id": 1, "sales.sum": -1 } },
{ "$group": {
"_id": "$_id",
"sales": { "$push": "$sales" }
}},
{ "$sort": { "sales.sum": -1 } }
])
Your current documents can be treated this way by using JavaScript evaluation with mapReduce, but don't do it that way as it will be much slower.
来源:https://stackoverflow.com/questions/24824397/mongodb-sort-by-subdocument-with-unknown-name