0

Is there a way to specify the order of keys to sort by?

There seems to be some confusion in the comments. To be clear, I'm not asking about ascending or descending order. I'm asking if I can specify sorting priority.

For example, I want to sort by:

  • pinned (Boolean)
  • score (Number)
  • newest (Date or ObjectId)

so that

  • only docs with the same pinned value get sorted by score, and
  • only docs with the same pinned and score get sorted by newest?

In other words,

  • score, newest should never be considered if pinned value is different (just sort by pinned)
  • newest should never be considered if score is different.

For example,

{ pinned: false, score:1, _id: new }
{ pinned: true, score:1, _id: oldest }
{ pinned: false, score:2, _id: old }

should be ordered as

{ pinned: true,  score: 1, _id: oldest }
{ pinned: false, score: 1, _id: new }
{ pinned: false, score: 2, _id: old }
14
  • IMHO, it would be easier for people to reply if you put some sample data... Commented Apr 25, 2014 at 2:41
  • I didn't think the question was that complex, but I've added an example. Commented Apr 25, 2014 at 2:45
  • 1
    are you using the mongo shell for your testing? In mongo order is significant in objects in several places. Sort clause is one of them. Index specification is another. Commented Apr 25, 2014 at 4:21
  • 1
    @AsyaKamsky can you make that an answer? It's the only response that gets to the root of the solution (that mongodb doesn't follow Ecmascript) Commented Apr 25, 2014 at 4:34
  • 1
    According to JSON spec yes it should be an unordered collection. However, here the order does matter. Commented Apr 25, 2014 at 4:35

2 Answers 2

2

While JSON documents are unordered, in MongoDB there are several places where order matters. The most important ones to remember are:

  • sort order
  • index specification order

When you specify a sort, the sort order will follow the order of fields, so in your case it would be .sort({pinned:1,score:1,newest:1}) you can see an example in the documentation.

Some operations expect fields in particular order.

It also matters for subdocuments if you are trying to match them (whereas top level field order in the query does not matter).

Sign up to request clarification or add additional context in comments.

4 Comments

How can MongoDB distinguish between the identical objects {score:1,newest:1} and {newest:1,score:1}
They are not identical in their bson representation at all. Look at them as strings, for example - not at all identical and have a clearly defined sort order.
Their string (or bson) representations are not identical but as JavaScript objects - they are indistinguishable, as the key order is not guaranteed. So if I do .sort(obj) with JS object obj inside, I don't see how to reliably declare the order between the fields.
BTW I find Mongo's description of Bson vs Json very confusing and obscure: mongodb.com/json-and-bson is saying "MongoDB represents JSON documents in binary-encoded format called BSON behind the scenes". So is Bson only used behind the scene?
1

So I inserted some sample data as is in your question with mongo shell:

db.test.insert({ pinned: false, score:1, _id: "new" });
db.test.insert({ pinned: true, score:1, _id: "oldest" });
db.test.insert({ pinned: false, score:2, _id: "old" });

Try to sort it by:

db.test.find().sort({pinned: -1, score: 1, _id: 1})

It turns out the result is:

{ "_id" : "oldest", "pinned" : true, "score" : 1 }
{ "_id" : "new", "pinned" : false, "score" : 1 }
{ "_id" : "old", "pinned" : false, "score" : 2 }

Isn't that what you want?

EDIT: Keep in mind that JavaScript doesn't strictly obey JSON spec. e.g. JSON spec also says property names should quoted with ", JavaScript however you don't have to quote, or you can quote with '.

4 Comments

Thanks for your responses above and here! It turns out that I had a typo in my sort query - and so it was ignoring both score and _id. I really appreciate your help, but next time, it'd be a lot more helpful if you explained the "why" along with the "what". edit: and I see you added it right before I posted this comment. :+1:
I'd like to explain why over what. I just didn't know which part confused you.
Actually, it's specifically stated as unordered in both JSON and ECMAScript. I wonder why the MongoDB devs decided to ignore it.
It's not mongodb doesn't want to obey the spec, it's JavaScript doesn't. And mongo shell is based on JavaScript V8 engine. I added another example in my answer. I though people using JavaScript know about this trick, and didn't know you stuck there.

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.