4

I'm building a node.js application with Mongoose and have a problem related to sorting embedded documents. Here's the schema I use:

var locationSchema = new Schema({
    lat: { type: String, required: true },
    lon: { type: String, required: true },
    time: { type: Date, required: true },
    acc: { type: String }
})

var locationsSchema = new Schema({
    userId: { type: ObjectId },
    source: { type: ObjectId, required: true },
    locations: [ locationSchema ]
});

I'd like to output the locations embedded in the userLocations documented sorted by their time attribute. I currently do the sorting in JavaScript after I retrieved the data from MongoDb like so:

function locationsDescendingTimeOrder(loc1, loc2) {
   return loc2.time.getTime() - loc1.time.getTime()
}

LocationsModel.findOne({ userId: theUserId }, function(err, userLocations) { 
   userLocations.locations.sort(locationsDescendingTimeOrder).forEach(function(location) {
      console.log('location: ' + location.time);
   }
});

I did read about the sorting API provided by Mongoose but I couldn't figure out if it can be used for sorting arrays of embedded documents and if yes, if it is a sensible approach and how to apply it to this problem. Can anyone help me out here, please?

Thanks in advance and cheers, Georg

BumbleGee
  • 2,031
  • 3
  • 18
  • 18

2 Answers2

4

You're doing it the right way, Georg. Your other options are either to sort locations by time upon embedding in the first place, or going the more traditional non-embedded route (or minimally embedded route so that you may be embedding an array of ids or something but you're actually querying the locations separately).

glortho
  • 13,120
  • 8
  • 49
  • 45
  • Thanks Jed. I ended up using the approach you proposed - sorting the locations upon embedding. Works fine for me. – BumbleGee Feb 23 '12 at 16:36
  • That's my problem too, but how can I sort embedded documents upon embedding ? – drinchev Apr 01 '12 at 13:10
  • I've figured it out. You probably mean when adding new document via .push OR .unshift it will be positioned correctly. – drinchev Apr 01 '12 at 13:34
0

This also can be done using mongoose sort API as well.

LocationsModel.findOne({ userId: theUserId })
//    .sort({ "locations.time": "desc" }) // option 1
    .sort("-locations.time")              // option 2
    .exec((err, result) => {
        // compute fetched data
    })

Sort by field in nested array with Mongoose.js

More methods are mentioned in this answer as well

Sorting Options in mogoose

Mongoose Sort API