1

According to Mongo's docs, you can specify multiple sort keys like this:

{ $sort : { age : -1, posts: 1 } }

Which they say will sort first by age (descending) then by posts (ascending).

But the sort query is a Javascript object. To the best of my knowledge, although implementations typically iterate over properties in the order they were created, that's not actually part of ECMAScript's spec: object properties officially have no order.

Is MongoDB really relying on arbitrary behavior that could vary by implementation, am I wrong about the ECMAScript spec, or am I missing something in the Mongo docs that lets you tune the precedence some other way?

Semicolon
  • 4,783
  • 1
  • 23
  • 35

2 Answers2

1

Yes you are wrong about the ECMAScript spec. Properties retain their order which is why with some drivers for languages ( e.g Perl orders "hashes" by key name by default, use Tie::IxHash to change that) recommend forms that also maintain an order in the structure to be converted.

At any rate, this is not "really" JavaScript anyhow, but it is BSON. It is borrowed behavior anyhow so the statement really remains the same. The order you specify is preserved.

Neil Lunn
  • 130,590
  • 33
  • 275
  • 280
  • As of 2011, the spec explicitly said object properties have no sequence. Do you have a link to a later edition saying otherwise? Also, I'm pretty sure Mongo runs V8 ... documents are stored in BSON (which is a data format, not an execution context...?), but queries are executed in V8 (Javascipt). – Semicolon Aug 31 '14 at 06:49
  • ECMA-262 seems to be current. That's where I found it states there is no guaranteed sequence. I haven't checked Harmony yet though. FWIW, the JSON spec also says object properties have no guaranteed sequence, and BSON is a JSON derivitive (which doesn't mean it doesn't alter that behavior, but this seems pretty consistent). – Semicolon Aug 31 '14 at 06:55
  • @Semicolon The order will always be preserved as specified. As I said there are cases in other languages where translatable structures are generally otherwise ordered by default and you need to apply some method to make sure the order is preserved. But I know of no case where this applies to JavaScript, JSON or BSON. So whatever you are reading would seem to be incorrect. – Neil Lunn Aug 31 '14 at 07:03
  • I'm reading the *ECMAScript specification*. It's true that V8 and all browsers except certain versions of IE do preserve sequence, but it's unspecified behavior (and apparently early versions of V8 also didn't preserve sequence). De facto or not, it strikes me as odd that Mongo would rely on it. http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – Semicolon Aug 31 '14 at 07:11
  • @Semicolon What I am saying is produce a case where what I have said is not true and then you have your own answer. If you cannot then what I have said is true. That is basically how we solve problems. Disprove a statement or prove it. – Neil Lunn Aug 31 '14 at 07:21
  • I just did: early versions of V8 and IE -- and Firefox used to iterate in other sequences, too, and all of this was correct behavior according to the ECMAScript spec, which is literally the definition of Javascript. I'm not suggesting it won't *work* in MongoDB; it clearly does. But I think I *have* proven it's unspecified behavior. See the link in my last comment for a deep discussion of object property sequence in JS with many more good links to follow. – Semicolon Aug 31 '14 at 07:26
  • @Semicolon But is **is** MongoDB as brought up by your own tagging and my explicit response where I say this is BSON and nothing else. It is not MongoDB specific but how it **should** be implemented and is implemented by the code which is used. Pretty simple, but you seem to be after an argument and not an answer. I just give answers and don't do arguments. Argue with someone else or just accept that this will never happen with MongoDB, but it is not a specified behavior. – Neil Lunn Aug 31 '14 at 07:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60326/discussion-between-semicolon-and-neil-lunn). – Semicolon Aug 31 '14 at 07:40
1

The console is special, its objects are actually ordered unlike normal EMCAscript so that this can happen.

Here is a linked question from a 10gen employee that states: https://stackoverflow.com/a/18514551/383478

Among other things, order of fields is always preserved.

N.B: It is good to note that V8 (runs MongoDB shell and MR since v2.2 about) has ordered objects in practice anyway.

The only true way in non-V8 JS to keep order is to do key lookups like: How to keep an Javascript object/array ordered while also maintaining key lookups?

Community
  • 1
  • 1
Sammaye
  • 40,888
  • 7
  • 90
  • 139
  • Thanks, Sammaye. I should have made the question clearer: I understood that it will work regardless because of V8, but the thrust of my question wasn't "will it work?" it was "is this how it's implemented?" I thought there might be some more explicit way to declare the sequence. The 10gen answer is a good summary of what Neil was saying, except that it acknowledges JS outside of V8 may not behave the same, which is what made me find this odd (I sometimes have queries originating client-side -- so it's JS/JSON end to end, but I can't be 100% sure property order is preserved). – Semicolon Aug 31 '14 at 10:02
  • @Semicolon it does? He says EMCAScript holds order by spec but I say that the shell is special. He says the console is actually written in BSON which is also not true, you are right it is EMCAScript, V8 variant. Quite different in my mind but ok. If you have queries originating from node.js they will be ordered but if you have queries originating in the browser there is no way to guaranteee order. – Sammaye Aug 31 '14 at 10:05
  • @Semicolon I suppose you can do a key lookup to keep order in browsers: http://stackoverflow.com/questions/5773950/how-to-keep-an-javascript-object-array-ordered-while-also-maintaining-key-lookup this could also allow you to declare the seqeunce differently from different queries – Sammaye Aug 31 '14 at 10:05
  • Well, his main point anyway, as I understood it, which was that it "shouldn't be a concern" I guess? I was baffled by the BSON bit but not 100% sure on that point. In doing the research I was surprised to find just how much browsers have varied in their implementation: http://stackoverflow.com/a/8704349/1631952 . My solution for now is to pass the sort parameters from the browser as an array and create the sort-object server side. (If you want to adjust the answer a bit to state that property sequence is the only way to specify the precedence I'll go ahead and mark it accepted.) – Semicolon Aug 31 '14 at 10:10
  • @Semicolon V8 is special, it goes against the spec in allowing ordered objects and is implemented only in opera and chrome currently. Hmm that answer says spidermonkey also keeps order now, firefox have been known to copy Google so maybe... – Sammaye Aug 31 '14 at 10:17