1

If I have a document like this

{
    "_id" : "word",
    "nextWords" : {
        "x" : 3,
        "y" : 2,
        "z" : 1,
        "h" : 1,
        "n" : 10
    }
}

and I want to return the objects in "nextWords" sorted in a descending order.

Can I do that either in MongoDB Shell or Java?

Edit: I want "nextWords" sorted in a descending order according to its value, so the expected output is:

{
    "n" : 10
    "x" : 3,
    "y" : 2,
    "z" : 1,
    "h" : 1,
}
eqladios
  • 68
  • 1
  • 8
  • { $push: { : { $each: [ , , ... ], $sort: } } } – Robus Apr 30 '16 at 20:39
  • Please could you elaborate more? where should I pass this? and if it is an update operation I want it to be applied for the whole document and I think that would be hard to write – eqladios Apr 30 '16 at 21:04
  • In short: you can not with this data model. The order in which fields are returned is simply arbitrary. You need to do the sort programmatically in your code. – Markus W Mahlberg Apr 30 '16 at 21:09
  • Thanks for you comment, how do you think I can return "nextWords" in a data structure in Java and then sort it by its value? is it doable in this model? – eqladios Apr 30 '16 at 22:25
  • You can sort an array, but not a set of fields. They have no order. – BanksySan Apr 30 '16 at 22:53
  • Possible duplicate of [Does the sequence of the values matter in a JSON object?](http://stackoverflow.com/questions/16870416/does-the-sequence-of-the-values-matter-in-a-json-object) – BanksySan Apr 30 '16 at 22:55
  • I think I wasn't clear, I edited my question and I hope it's more clear now – eqladios May 01 '16 at 00:00

2 Answers2

0

JSON objects have no order. From the specs section 4.3.3:

An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

You cannot rely on the order of a field, it isn't guaranteed.

BanksySan
  • 27,362
  • 33
  • 117
  • 216
-1

you could instead do it as follows

{ "_id" : "word", "nextWords" : [ {"word" : "x","count" : 3 },.... ] }

use this map reduce:

String map = "function() { for(i in this.nextWords)emit(i.word,i.count) }

String reduce = "function(key,value){return (value);}";

run it in java:

MapReduceCommand cmd = new MapReduceCommand(collection, map, reduce, null, MapReduceCommand.OutputType.INLINE, null);

MapReduceOutput out = collection.mapReduce(cmd);

for (DBObject o : out.results()) {
       // here put them in an array 
    }

//sort the array

  • The order of the emitted values may or may not be in order. And your map reduce does not change this fact. Furthermore, with that structure, the map/reduce is totally unneeded, as `db.words.aggregate({$unwind:"$nextWords"},{$sort:{"$nextWord.count":-1}},{$group:{_id:"$word",sorted:{$push:"$nextWord"}}})` would do the same, plus the iteration you put into the code. – Markus W Mahlberg Apr 30 '16 at 20:50
  • I wrote it that way because using mongodb's api in java makes it hard to access nested sub documents. http://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection – Yasser Khaled Apr 30 '16 at 21:00
  • You can do aggregations with the Java driver. ;) And I doubt that you need a m/r to access subdocs. – Markus W Mahlberg Apr 30 '16 at 21:06