diff --git a/README.md b/README.md index 4fbb6abcc..69f55b9b8 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ of type `GeoPoint`. This allows for indexed ```near``` queries. Default is `fal - It will try to establish the connection automatically once users hit the endpoint. If the mongodb server is offline, the app will start, however, the endpoints will not work. - **disableDefaultSort**: Set to `true` to disable the default sorting behavior on `id` column, this will help performance using indexed columns available in mongodb. +- **collation**: Specify language-specific rules for string comparison, such as rules for lettercase and accent marks. See [`MongdoDB documentation`](https://docs.mongodb.com/manual/reference/collation/) for details. It can also be used to create [`case insensitive indexes`](https://docs.mongodb.com/manual/core/index-case-insensitive/). ### Setting the url property in datasource.json diff --git a/lib/mongodb.js b/lib/mongodb.js index f0e3c6035..3b23fd886 100644 --- a/lib/mongodb.js +++ b/lib/mongodb.js @@ -1315,6 +1315,11 @@ MongoDB.prototype.all = function all(model, filter, options, callback) { return callback(err); } + var collation = options && options.collation; + if (collation) { + cursor.collation(collation); + } + // don't apply sorting if dealing with a geo query if (!hasNearFilter(filter.where)) { var order = self.buildSort(model, filter.order, options); diff --git a/test/mongodb.test.js b/test/mongodb.test.js index 426f1f585..792f1b8bb 100644 --- a/test/mongodb.test.js +++ b/test/mongodb.test.js @@ -255,6 +255,13 @@ describe('mongodb connector', function() { Category = db.define('Category', { title: {type: String, length: 255, index: true}, posts: {type: [db.ObjectID], index: true}, + }, { + indexes: { + 'title_case_insensitive': { + keys: {title: 1}, + options: {collation: {locale: 'en', strength: 1}}, + }, + }, }); PostWithStringIdAndRenamedColumns = db.define( @@ -314,7 +321,9 @@ describe('mongodb connector', function() { PostWithNumberUnderscoreId.destroyAll(function() { PostWithStringId.destroyAll(function() { PostWithDisableDefaultSort.destroyAll(function() { - done(); + Category.destroyAll(function() { + done(); + }); }); }); }); @@ -508,6 +517,23 @@ describe('mongodb connector', function() { }); }); + it('should create case insensitive indexes', function(done) { + db.automigrate('Category', function() { + db.connector.db.collection('Category').indexes(function(err, result) { + if (err) return done(err); + var indexes = [ + {name: '_id_', key: {_id: 1}}, + {name: 'title_1', key: {title: 1}}, + {name: 'title_case_insensitive', key: {title: 1}, collation: {locale: 'en', strength: 1}}, + {name: 'posts_1', key: {posts: 1}}, + ]; + + result.should.containDeep(indexes); + done(); + }); + }); + }); + it('should have created models with correct _id types', function(done) { PostWithObjectId.definition.properties._id.type.should.be.equal( db.ObjectID @@ -2679,6 +2705,22 @@ describe('mongodb connector', function() { }); }); + it('should allow to find using case insensitive index', function(done) { + Category.create({title: 'My Category'}, function(err, category1) { + if (err) return done(err); + Category.create({title: 'MY CATEGORY'}, function(err, category2) { + if (err) return done(err); + + Category.find({where: {title: 'my cATEGory'}}, {collation: {locale: 'en', strength: 1}}, + function(err, categories) { + if (err) return done(err); + categories.should.have.length(2); + done(); + }); + }); + }); + }); + it('should allow to find using like', function(done) { Post.create({title: 'My Post', content: 'Hello'}, function(err, post) { Post.find({where: {title: {like: 'M.+st'}}}, function(err, posts) {