How can I sort a MongoDB collection by a given field, case-insensitively? By default, I get A-Z before a-z.
11 Answers
Update: As of now mongodb have case insensitive indexes:
Users.find({})
.collation({locale: "en" })
.sort({name: 1})
.exec()
.then(...)
shell:
db.getCollection('users')
.find({})
.collation({'locale':'en'})
.sort({'firstName':1})
Update: This answer is out of date, 3.4 will have case insensitive indexes. Look to the JIRA for more information https://jira.mongodb.org/browse/SERVER-90
Unfortunately MongoDB does not yet have case insensitive indexes: https://jira.mongodb.org/browse/SERVER-90 and the task has been pushed back.
This means the only way to sort case insensitive currently is to actually create a specific "lower cased" field, copying the value (lower cased of course) of the sort field in question and sorting on that instead.
-
So there is no option for sorting the results with insensitive unless creating a new field with lower or upper cased values only. ryt?? – Varun Kumar Apr 08 '14 at 11:07
-
1@VarunKumar yep it is one of the bad points of MongoDB, I personally wouldn't use the below answer, MongoDB will be limited to 32meg of sort without the index resulting in very small result sets being allowed. – Sammaye Apr 08 '14 at 11:16
-
1@VarunKumar to be more precise you will be limited to between sorting 2 to 32,000 records depending on the size of the documents, not only that but the sort will be completely in memory, which will be a killer – Sammaye Apr 08 '14 at 11:17
-
Holy *** it finally has! – Sammaye Sep 16 '16 at 18:16
-
@SSHThis can you please share the link where it is resolved? – Rahul Matte Sep 27 '16 at 08:28
-
@RahulMatte click on the JIRA link, it is resolved in the latest unstable, as are collations – Sammaye Sep 27 '16 at 08:43
-
Having said in the JIRA link, case insensitive index will come out with MongoDB v. 3.3.11 which basically you need to upgrade the mongodb for this feature. you can find new version here but as of today it is 3.2.10, the new version could be release in the future- https://www.mongodb.com/download-center#community – Teerakiat Chitawattanarat Oct 23 '16 at 01:33
-
This is resolved by MongoDB. Take a look at my answer bellow – Mladen Janjetovic Feb 28 '17 at 14:19
-
@Sammaye is there some way I can use `case insensitive index` with `reactive-mongo` driver ? I am using `scala` with `mongo`. – oblivion Jul 31 '17 at 09:58
-
@oblivion unfortunately I do not program in Scala – Sammaye Jul 31 '17 at 10:07
-
Collations are supported by aggregate so I would say yes – Sammaye Dec 14 '17 at 09:18
-
1@F.H. are you using collations? – Sammaye Jul 15 '19 at 13:39
-
1@F.H. to be clear the reason why sort is case sensitive without collations ios because it uses lexical sorting without collations – Sammaye Jul 15 '19 at 13:40
-
**update** sorry, had wrong collation object passed - *confirmed it works with aggregation* – F.H. Jul 15 '19 at 13:43
-
Good answer. I just wanna add some documentation: https://docs.mongodb.com/manual/reference/collation – code đờ Jun 22 '21 at 07:57
Sorting does work like that in MongoDB but you can do this on the fly with aggregate:
Take the following data:
{ "field" : "BBB" }
{ "field" : "aaa" }
{ "field" : "AAA" }
So with the following statement:
db.collection.aggregate([
{
"$project": {
"field": 1,
"insensitive": { "$toLower": "$field" }
}
},
{ "$sort": { "insensitive": 1 } }
])
Would produce results like:
{
"field" : "aaa",
"insensitive" : "aaa"
},
{
"field" : "AAA",
"insensitive" : "aaa"
},
{
"field" : "BBB",
"insensitive" : "bbb"
}
The actual order of insertion would be maintained for any values resulting in the same key when converted.
-
Yup.. this looks gud.. but I want to implement the same from a java code.. So it'll more helpful if you share me that how this can be achieved from Java class with handling mongodb and query object. – Varun Kumar Apr 08 '14 at 11:10
-
@VarunKumar You basically need to construct DBObject entries that you pass to the aggregate method. There is [this example](http://docs.mongodb.org/ecosystem/tutorial/use-aggregation-framework-with-java-driver/) in the documentation resources. So it should not be hard to translate. And considering that it is an actual answer to show how it can be done that should not be too hard. – Neil Lunn Apr 08 '14 at 11:30
-
Would this be slow (i.e. does the aggregate get evaluated every time?) – Archimedes Trajano Mar 19 '16 at 00:13
-
-
This has been an issue for quite a long time on MongoDB JIRA, but it is solved now. Take a look at this release notes for detailed documentation. You should use collation
.
User.find()
.collation({locale: "en" }) //or whatever collation you want
.sort({name:1})
.exec(function(err, users) {
// use your case insensitive sorted results
});

- 107,154
- 87
- 232
- 265

- 13,844
- 8
- 72
- 82
Adding the code .collation({'locale':'en'})
helped to solve my issue.

- 2,889
- 1
- 22
- 43

- 360
- 3
- 9
-
But when I use collation in Mongoose with aggregation, I get an error MongooseError: Callback must be a function, got [object Object] – Monu Chaudhary Apr 02 '19 at 08:40
As of now (mongodb 4), you can do the following:
mongo shell:
db.getCollection('users')
.find({})
.collation({'locale':'en'})
.sort({'firstName':1});
mongoose:
Users.find({})
.collation({locale: "en" })
.sort({name: 1})
.exec()
.then(...)
Here are supported languages and locales by mongodb.

- 2,827
- 2
- 28
- 37
In Mongoose:-
Customer.find()
.collation({locale: "en" })
.sort({comapany: 1})

- 71
- 1
- 7
Here it is in Java. I mixed no-args and first key-val variants of BasicDBObject
just for variety
DBCollection coll = db.getCollection("foo");
List<DBObject> pipe = new ArrayList<DBObject>();
DBObject prjflds = new BasicDBObject();
prjflds.put("field", 1);
prjflds.put("insensitive", new BasicDBObject("$toLower", "$field"));
DBObject project = new BasicDBObject();
project.put("$project", prjflds);
pipe.add(project);
DBObject sort = new BasicDBObject();
sort.put("$sort", new BasicDBObject("insensitive", 1));
pipe.add(sort);
AggregationOutput agg = coll.aggregate(pipe);
for (DBObject result : agg.results()) {
System.out.println(result);
}

- 305,182
- 66
- 621
- 471

- 7,057
- 3
- 23
- 33
If you want to sort and return all data in a document, you can add document: "$$ROOT"
db.collection.aggregate([
{
$project: {
field: 1,
insensitive: { $toLower: "$field" },
document: "$$ROOT"
}
},
{ $sort: { insensitive: 1 } }
]).toArray()

- 33
- 4
Tried all the above and answers Consolidating the result
Answer-1:
db.collection.aggregate([
{ "$project": {
"field": 1,
"insensitive": { "$toLower": "$field" }
}},
{ "$sort": { "insensitive": 1 } } ])
Aggregate query converts the field into lower, So performance is low for large data.
Answer-2:
db.collection.find({}).collation({locale: "en"}).sort({"name":1})
By default mongo follows uft-8 encoding(Z has high piriority then a) rules ,So overriding with language-specific rules. Its fast compare to above query Look into an official document to customize rules

- 159
- 1
- 6
MongoDB with Panache provided
public <T extends Entity> ReactivePanacheQuery<T> withCollation(Collation collation);
method in ReactivePanacheQuery
class.
Using this sorting the data with case-insensitive support can be achieved as follows.
repo.find(query, sort).withCollation(Collation.builder().locale("en").build())

- 46
- 4
We solve this problem with the help of .sort function in JavaScript array
Here is the code
function foo() { let results = collections.find({ _id: _id }, { fields: { 'username': 1, } }).fetch(); results.sort((a, b)=>{ var nameA = a.username.toUpperCase(); var nameB = b.username.toUpperCase(); if (nameA nameB) { return 1; } return 0; }); return results; }

- 1
- 2