Stuart Brown
Stuart Brown

Reputation: 987

Order results from MongoDB Query

I'm executing a MongoDB query in ExpressJS via Mongoose.

I have documents that look like the below

{
"name": "first",
"spellings": [
"here",
"is",
"you"
],
"keyStageLevel": 4,
"spellingLevel": 2,
"__v": 0
},
{
"name": "second",
"spellings": [
"her",
"is",
"another"
],
"keyStageLevel": 2,
"spellingLevel": 3,
"__v": 0
},
{
"name": "third",
"spellings": [
"snother",
"list"
],
"keyStageLevel": 2,
"spellingLevel": 4,
"__v": 0
}

I would like to have the result of my query returned so that 1) the keyStageLevel are in order and 2) within each keyStageLevel the spellingLevel are shown in order with the details of the document.

keyStageLevel 2  
    spellingLevel 3
        name: "second",
        "spellings": [
            "her",
            "is",
            "another"
            ]
    spellingLevel 4
        name: "third",
        "spellings": [
        "snother",
        "list"
        ]
keyStageLevel 4
    spellingLevel 2

    etc

My code currently runs var spellings = await Spelling.aggregate([{"$group" : {_id:{keyStageLevel:"$keyStageLevel",spellingLevel:"$spellingLevel"}}} ]);

which retuns

[
    {
    "_id": {
        "keyStageLevel": 2,
        "spellingLevel": 4
        }
    },
    {
        "_id": {
        "keyStageLevel": 2,
        "spellingLevel": 3
        }
    },
    {
        "_id": {
        "keyStageLevel": 5,
        "spellingLevel": 1
        }
    },
    {
        "_id": {
        "keyStageLevel": 4,
        "spellingLevel": 2
        }
    }
]

Many thanks for any help.

Upvotes: 0

Views: 38

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151072

What you are mostly after is using $group to accumulate the remaining document data under each "keyStageLevel" this is done using $push. If you want results in specific order then you always need to $sort, being both before and after feeding to a $group stage:

var spellings = await Spelling.aggregate([
  { "$sort": { "keyStageLevel": 1, "spellingLevel": 1 } },
  { "$group" : {
    "_id": { "keyStageLevel": "$keyStageLevel" },
    "data": {
      "$push": {
         "spellingLevel": "$spellingLevel",
         "name": "$name",
         "spellings": "$spellings"
      }
    }
  }},
  { "$sort": { "_id": 1 } }
])

The first $sort ensures the items added via $push are accumulated in that order, and the final ensures that the "output" is actually sorted in the desired order, as $group will likely not always return the grouped keys in any specific order unless you instruct with such a stage.

This will give you output like:

{
        "_id" : {
                "keyStageLevel" : 2
        },
        "data" : [
                {
                        "spellingLevel" : 3,
                        "name" : "second",
                        "spellings" : [
                                "her",
                                "is",
                                "another"
                        ]
                },
                {
                        "spellingLevel" : 4,
                        "name" : "third",
                        "spellings" : [
                                "snother",
                                "list"
                        ]
                }
        ]
}
{
        "_id" : {
                "keyStageLevel" : 4
        },
        "data" : [
                {
                        "spellingLevel" : 2,
                        "name" : "first",
                        "spellings" : [
                                "here",
                                "is",
                                "you"
                        ]
                }
        ]
}

Upvotes: 1

Related Questions