Randomblue
Randomblue

Reputation: 116263

Mongoose: Sort alphabetically

I have a User model

var User = mongoose.model('Users',
    mongoose.Schema({
        username: 'string',
        password: 'string',
        rights: 'string'
    })
);

I want to get all the users, sorted alphabetically by username. This is what I have tried

User.find({}, null, {sort: {username: 1}}, function (err, users) {
    res.send(users);
});

However, this does not sort the users alphabetically. How can I sort alphabetically?

EDIT: I got confused because I was expecting a "purely alphabetically" sort from Mongoose, not one where Z > a. Basically, I wanted a sort based on username.toLowerCase().

Upvotes: 20

Views: 32169

Answers (2)

WillyC
WillyC

Reputation: 4705

This question and answer are a few years old, and from what I can tell there is now a correct way to do this. Providing this for future searchers:

User.find().collation({locale:'en',strength: 2}).sort({username:1})
    .then( (users) =>{ 
        //do your stuff
    });

You could also index on username without case sensitivity:

UserSchema.index({username:1}, {collation: { locale: 'en', strength: 2}});

strength:1 is another option - best to refer to the documentation to decide which works best for you.

For the details of all this, look here.

Upvotes: 29

mjhm
mjhm

Reputation: 16685

EDIT: Per the comment the issue turns out to be sorting on toLowerCase(username). MongoDB doesn't have a built in method for complex sorting. So there are essentially two ways to go:

  1. Add a usernameLowerCase field to the Schema. This is the better option if you need to do this a lot.
  2. Perform an aggregation with a projection using the $toLower operator to dynamically generate a usernameLowerCase field. This comes with performance and memory caveats, but it may be the more convenient choice.

Original Answer: Here's a complete example that sorts correctly using the specific code from the question. So there must be something else going on:

#! /usr/bin/node

var mongoose = require('mongoose');
mongoose.connect('localhost', 'test');
var async = require('async');

var User = mongoose.model('Users',
    mongoose.Schema({
        username: 'string',
        password: 'string',
        rights: 'string'
    })
);

var userList = [
    new User({username: 'groucho', password: 'havacigar', rights: 'left'}),
    new User({username: 'harpo', password: 'beepbeep', rights: 'silent'}),
    new User({username: 'chico', password: 'aintnosanityclause', rights: 'all'})
];

async.forEach(userList, 
    function (user, SaveUserDone) {
        user.save(SaveUserDone);
    },
    function (saveErr) {
        if (saveErr) {
            console.log(saveErr);
            process.exit(1);
        }
        User.find({}, null, {sort: {username: 1}}, function (err, users) {
            if (err) {
                console.log(err);
                process.exit(1);
            }
            console.log(users);
            process.exit(0);
        });
    }
);

Upvotes: 25

Related Questions