0

Given documents like

{
   ...
   name:'whatever',
   games: [122, 199, 201, 222]
}

db.col.aggregate({$match:{}},
    {$sort:{'games.0': -1}})

doesn't sort ... no errors ... it just doesn't sort on the first array element of the games array.

Although a query with the same syntac .. works fine

col.find({}).sort({'games.0':-1}) 

if I change the collection so games is an array of objects like

   [ {game1:198}, {game2:201} ...]

then the aggregation works using

{$sort:{'games.game1': -1}})

what am I missing to get this to work with an array of numbers?

3
  • I see what you are trying to do here in general. But may I ask, what is the purpose/benefit of ordering the collection results by the first element of the array? It might just shed some light if you explained what the rest of your intended operations are mean to do. BTW. Just doing { "$sort": { "games": -1 } } will implicitly sort on the first element anyway. Commented Jun 10, 2015 at 3:30
  • Although the 'real' data set is a bit more complicated .. what I'm essentially doing is asking 'what were the top scores for the nth game'. So a 'games.3' will return the high scores for the 4th game at the top of the document list. What I really want to know is why this type of sort (indexed off an array primitive) works for regular queries but doesn't in an aggregation. Commented Jun 10, 2015 at 22:50
  • I came across your question while answering this question. In 3.6 version all the find and aggregation semantics issues have been corrected to make them consistent. So your aggregation sort should work same as find sort. Maybe little too late for you but I wanted to leave comment. Commented Jul 26, 2018 at 20:22

3 Answers 3

0

Try unwinding the array first by applying the $unwind operator on the array, then use $sort on the deconstructed array and finally use $group to get the original documents structure:

db.coll.aggregate([
    {"$unwind": "$games"},
    {"$sort": {"games": 1}},
    {
        "$group": {
            "_id": "$_id",
            "name": {"$first": "$name"},
            "games": {"$push": "$games"}
        }
    }
])
Sign up to request clarification or add additional context in comments.

1 Comment

This will scramble the order of the games. The games array must not be changed as it contains the ordered scores for the individual matches.... and the 'real' document is much larger and there are a lot of them .... not sure I would want to increase the memory footprint 4 times by unwinding .... I'll probably just run map/reduce ... though I'm still surprised by not being able to do the 'simple' sort ... thanks for trying.
0

Try this:

db.coll.aggregate([
    {"$unwind": "$games"},
    {"$sort": {"games": -1}}
]}

I hope this will work for you as you expected.

Comments

0

In mongo 3.4 find sort i.e. db.col.find({}).sort({'games.0':-1}) works as expected whereas aggregation sort doesn't.

In mongo 3.6 both find and aggregation sort works as expected.

Jira issue for that: https://jira.mongodb.org/browse/SERVER-19402

I would recommend you to update your mongo version and your aggregation query will work fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.