Skip to content

Commit 71879c3

Browse files
authored
fix(cursor): cursor count with collation fix
When a collation set is applied to a cursor, the count method reflects this and returns the correct value. Fixes NODE-1369
1 parent 38213dc commit 71879c3

File tree

4 files changed

+66
-13
lines changed

4 files changed

+66
-13
lines changed

lib/collection.js

+1-11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const toError = require('./utils').toError;
1313
const normalizeHintField = require('./utils').normalizeHintField;
1414
const handleCallback = require('./utils').handleCallback;
1515
const decorateCommand = require('./utils').decorateCommand;
16+
const decorateWithCollation = require('./utils').decorateWithCollation;
1617
const formattedOrderClause = require('./utils').formattedOrderClause;
1718
const ReadPreference = require('mongodb-core').ReadPreference;
1819
const CommandCursor = require('./command_cursor');
@@ -2279,17 +2280,6 @@ var findAndRemove = function(self, query, sort, options, callback) {
22792280
self.findAndModify(query, sort, null, options, callback);
22802281
};
22812282

2282-
function decorateWithCollation(command, self, options) {
2283-
// Do we support collation 3.4 and higher
2284-
var capabilities = self.s.topology.capabilities();
2285-
// Do we support write concerns 3.4 and higher
2286-
if (capabilities && capabilities.commandsTakeCollation) {
2287-
if (options.collation && typeof options.collation === 'object') {
2288-
command.collation = options.collation;
2289-
}
2290-
}
2291-
}
2292-
22932283
function decorateWithReadConcern(command, self, options) {
22942284
let readConcern = Object.assign({}, command.readConcern || {});
22952285
if (self.s.readConcern) {

lib/cursor.js

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const f = require('util').format;
55
const deprecate = require('util').deprecate;
66
const formattedOrderClause = require('./utils').formattedOrderClause;
77
const handleCallback = require('./utils').handleCallback;
8+
const decorateWithCollation = require('./utils').decorateWithCollation;
89
const ReadPreference = require('mongodb-core').ReadPreference;
910
const MongoError = require('mongodb-core').MongoError;
1011
const Readable = require('stream').Readable;
@@ -1013,6 +1014,9 @@ var count = function(self, applySkipLimit, opts, callback) {
10131014
command.hint = self.s.cmd.hint;
10141015
}
10151016

1017+
// Apply a collation if set
1018+
decorateWithCollation(command, self, self.s.cmd);
1019+
10161020
if (typeof opts.maxTimeMS === 'number') {
10171021
command.maxTimeMS = opts.maxTimeMS;
10181022
} else if (self.s.cmd && typeof self.s.cmd.maxTimeMS === 'number') {

lib/utils.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,30 @@ function isPromiseLike(maybePromise) {
533533
return maybePromise && typeof maybePromise.then === 'function';
534534
}
535535

536+
/**
537+
* Applies collation to a given command.
538+
*
539+
* @param {object} [command] the command on which to apply collation
540+
* @param {(Cursor|Collection)} [target] target of command
541+
* @param {object} [options] options containing collation settings
542+
*/
543+
function decorateWithCollation(command, target, options) {
544+
const topology = target.s && target.s.topology;
545+
546+
if (!topology) {
547+
throw new TypeError('parameter "target" is missing a topology');
548+
}
549+
550+
// Do we support collation 3.4 and higher
551+
const capabilities = target.s.topology.capabilities();
552+
// Do we support write concerns 3.4 and higher
553+
if (capabilities && capabilities.commandsTakeCollation) {
554+
if (options.collation && typeof options.collation === 'object') {
555+
command.collation = options.collation;
556+
}
557+
}
558+
}
559+
536560
module.exports = {
537561
filterOptions,
538562
mergeOptions,
@@ -554,5 +578,6 @@ module.exports = {
554578
executeOperation,
555579
applyWriteConcern,
556580
convertReadPreference,
557-
isPromiseLike
581+
isPromiseLike,
582+
decorateWithCollation
558583
};

test/functional/collations_tests.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var test = require('./shared').assert;
33
var setupDatabase = require('./shared').setupDatabase;
44
var co = require('co');
55
var mock = require('mongodb-mock-server');
6+
const expect = require('chai').expect;
67

78
var defaultFields = {
89
ismaster: true,
@@ -1102,6 +1103,33 @@ describe('Collation', function() {
11021103
}
11031104
});
11041105

1106+
it('cursor count method should return the correct number when used with collation set', {
1107+
metadata: { requires: { mongodb: '>=3.4.0' } },
1108+
test: function(done) {
1109+
const configuration = this.configuration;
1110+
const client = configuration.newClient({ w: 1 }, { poolSize: 1, auto_reconnect: false });
1111+
1112+
client.connect(function(err, client) {
1113+
const db = client.db(configuration.db);
1114+
const docs = [{ _id: 0, name: 'foo' }, { _id: 1, name: 'Foo' }];
1115+
const collation = { locale: 'en_US', strength: 2 };
1116+
let collection, cursor;
1117+
const close = e => cursor.close(() => client.close(() => done(e)));
1118+
1119+
Promise.resolve()
1120+
.then(() => db.createCollection('cursor_collation_count'))
1121+
.then(() => (collection = db.collection('cursor_collation_count')))
1122+
.then(() => collection.insertMany(docs))
1123+
.then(() => collection.find({ name: 'foo' }).collation(collation))
1124+
.then(_cursor => (cursor = _cursor))
1125+
.then(() => cursor.count())
1126+
.then(val => expect(val).to.equal(2))
1127+
.then(() => close())
1128+
.catch(e => close(e));
1129+
});
1130+
}
1131+
});
1132+
11051133
/******************************************************************************
11061134
.___ __ __ .__
11071135
| | _____/ |_ ____ ________________ _/ |_|__| ____ ____
@@ -1125,7 +1153,13 @@ describe('Collation', function() {
11251153
var col = db.collection('collation_test');
11261154
// Create collation index
11271155
col.createIndexes(
1128-
[{ key: { a: 1 }, collation: { locale: 'nn' }, name: 'collation_test' }],
1156+
[
1157+
{
1158+
key: { a: 1 },
1159+
collation: { locale: 'nn' },
1160+
name: 'collation_test'
1161+
}
1162+
],
11291163
function(err) {
11301164
test.equal(null, err);
11311165

0 commit comments

Comments
 (0)