MongoDB: Sort by subdocument with unknown name

☆樱花仙子☆ 提交于 2019-12-11 03:21:38

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!