0

This is stemming from an example that was provided at how to sort array inside collection record in mongoDB

> alit=[{a:16},{a:15},{a:14},{a:13},{a:12},{a:11},{a:10},{a:9},{a:8},{a:7},{a:6},{a:5},{a:4},{a:3},{a:2},{a:1},{a:0}]
> alit.sort(function(a,b) {return a.a>b.a } ) 
[ { "a":8 }, { "a":0 }, { "a":7 }, { "a":14 }, { "a":12 }, { "a":11 }, { "a":10 }, { "a":9 }, { "a":1 }, { "a":13 }, { "a":6 }, { "a":5 }, { "a":4 }, { "a":3 }, { "a":2 }, { "a":15 }, { "a":16 } ] 
>

Note that if I execute this same line more times it gets progressively sorted more and more, it's as if this was executing a quicksort but with only two levels of recursion each time. Can anyone explain what I'm doing wrong and how to define a custom order that works in one sweep?

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Vini Bono
  • 85
  • 8
  • 1
    What are you talking about? The shell is just a plain JavaScript REPL and you are just sorting a plain JavaScript array with a regular JavaScript [`Array.sort()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) method. Works just like it should and certainly not how you are claiming. – Neil Lunn Jul 12 '17 at 02:05
  • I am able to verify the above assertion. I copied your statements into my Mongo shell and mixed up the numbers a bit. What I get as a result of the sort is the expected sorted array and not what you describe. For what it's worth, I used v3.4.2. – ThisClark Jul 12 '17 at 02:10
  • 1
    I'm using v3.0.10 and literally copy pasted my lines from the client. I'm not claiming anything, Neil. – Vini Bono Jul 14 '17 at 16:53

1 Answers1

0

The issue is with the custom comparison function you are using in your array sort.

Older versions of JavaScript engines (for example, those used in the MongoDB 3.0 and earlier shell) expect a custom comparison function will return one of three numeric values: positive (greater than), zero (equal), or negative (less than). Comparison functions returning boolean values have undefined outcomes (despite the reasonable expectation that these should be coerced to their numeric equivalents) so the result is dependent on the JavaScript engine.

You should get the expected outcome using a function which returns numeric values.

For example, this should work in all versions of the mongo shell:

 alit.sort(function(a,b) {return a.a - b.a } )

Note: the more modern SpiderMonkey engine used in mongo 3.2 or newer correctly handles sorting using >, so your original custom sort() will work as expected in recent versions of the shell.

Stennie
  • 63,885
  • 14
  • 149
  • 175
  • Got it. Thanks! It worked like a charm. I couldn't find good documentation on how to define the order or how it changed over time so i definitely appreciate the response! – Vini Bono Jul 14 '17 at 16:56
  • @ViniBono The `Array.sort()` behaviour lies within the JavaScript engine and variations between implementations have been a longstanding complaint (eg: https://stackoverflow.com/questions/3026281/array-sort-sorting-stability-in-different-browsers, https://www.allenpike.com/2009/arraysort-browser-differences/, https://stackoverflow.com/questions/42338978/is-it-really-a-array-sorting-bug-of-chrome-and-ie). If you are doing any significant client side programming or manipulation, typically this is better done in a driver implementation (eg. Node.js, Python, ...) rather than the `mongo` shell. – Stennie Jul 14 '17 at 21:28
  • 1
    @ViniBono You can find information on the JavaScript engines used in the MongoDB release notes, with the most recent change being a [move from V8 to SpiderMonkey](https://docs.mongodb.com/manual/release-notes/3.2-javascript/) (Mozilla's JS engine) in MongoDB 3.2. The `mongo` shell includes a command `interpreterVersion()` if you want to confirm what your shell is using. – Stennie Jul 14 '17 at 21:28