aboutsummaryrefslogtreecommitdiff
path: root/node_modules/mongodb/lib/collection.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/mongodb/lib/collection.js')
-rw-r--r--node_modules/mongodb/lib/collection.js146
1 files changed, 123 insertions, 23 deletions
diff --git a/node_modules/mongodb/lib/collection.js b/node_modules/mongodb/lib/collection.js
index bbe1e3b..5a94403 100644
--- a/node_modules/mongodb/lib/collection.js
+++ b/node_modules/mongodb/lib/collection.js
@@ -122,6 +122,8 @@ var Collection = function(db, topology, dbName, name, pkFactory, options) {
, promiseLibrary: promiseLibrary
// Read Concern
, readConcern: options.readConcern
+ // Collation
+ , collation: options.collation
}
}
@@ -280,6 +282,7 @@ Collection.prototype.find = function() {
// Add read preference if needed
newOptions = getReadPreference(this, newOptions, this.s.db, this);
+
// Set slave ok to true if read preference different from primary
if(newOptions.readPreference != null
&& (newOptions.readPreference != 'primary' || newOptions.readPreference.mode != 'primary')) {
@@ -351,6 +354,9 @@ Collection.prototype.find = function() {
findCommand.readConcern = this.s.readConcern;
}
+ // Decorate find command with collation options
+ decorateWithCollation(findCommand, this, options);
+
// Create the cursor
if(typeof callback == 'function') return handleCallback(callback, null, this.s.topology.cursor(this.s.namespace, findCommand, newOptions));
return this.s.topology.cursor(this.s.namespace, findCommand, newOptions);
@@ -507,9 +513,7 @@ Collection.prototype.insertMany = function(docs, options, callback) {
// Return a Promise
return new this.s.promiseLibrary(function(resolve, reject) {
- // console.log("########## insertMany 0")
bulkWrite(self, operations, options, function(err, r) {
- // console.log("########## insertMany 1")
if(err) return reject(err);
resolve(mapInserManyResults(docs, r));
});
@@ -601,9 +605,25 @@ var bulkWrite = function(self, operations, options, callback) {
// Create the bulk operation
var bulk = options.ordered == true || options.ordered == null ? self.initializeOrderedBulkOp(options) : self.initializeUnorderedBulkOp(options);
+ // Do we have a collation
+ var collation = false;
+
// for each op go through and add to the bulk
try {
for(var i = 0; i < operations.length; i++) {
+ // Get the operation type
+ var key = Object.keys(operations[i])[0];
+ // Check if we have a collation
+ if(operations[i][key].collation) {
+ collation = true;
+ }
+
+ // // Have we specified collation, apply it
+ // decorateWithCollation(operations[i], self, options);
+ // console.log("================ bulkWrite")
+ // console.dir(operations[i])
+
+ // Pass to the raw bulk
bulk.raw(operations[i]);
}
} catch(err) {
@@ -613,6 +633,12 @@ var bulkWrite = function(self, operations, options, callback) {
// Final options for write concern
var finalOptions = writeConcern(shallowClone(options), self.s.db, self, options);
var writeCon = finalOptions.writeConcern ? finalOptions.writeConcern : {};
+ var capabilities = self.s.topology.capabilities();
+
+ // Did the user pass in a collation, check if our write server supports it
+ if(collation && capabilities && !capabilities.commandsTakeCollation) {
+ return callback(new MongoError(f('server/primary/mongos does not support collation')));
+ }
// Execute the bulk
bulk.execute(writeCon, function(err, r) {
@@ -623,11 +649,6 @@ var bulkWrite = function(self, operations, options, callback) {
return callback(toError(r.getWriteErrorAt(0)), r);
}
- // console.log("!!!!!! BULK EXECUTE FINISHED")
- // console.dir(err)
- // console.dir(r)
-
- // if(err) return callback(err);
r.insertedCount = r.nInserted;
r.matchedCount = r.nMatched;
r.modifiedCount = r.nModified || 0;
@@ -1006,6 +1027,9 @@ var updateDocuments = function(self, selector, document, options, callback) {
op.upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
op.multi = typeof options.multi == 'boolean' ? options.multi : false;
+ // Have we specified collation
+ decorateWithCollation(finalOptions, self, options);
+
// Update options
self.s.topology.update(self.s.namespace, [op], finalOptions, function(err, result) {
if(callback == null) return;
@@ -1161,6 +1185,7 @@ Collection.prototype.deleteMany = function(filter, options, callback) {
var deleteMany = function(self, filter, options, callback) {
options.single = false;
+
removeDocuments(self, filter, options, function(err, r) {
if(callback == null) return;
if(err && callback) return callback(err);
@@ -1192,6 +1217,9 @@ var removeDocuments = function(self, selector, options, callback) {
var op = {q: selector, limit: 0};
if(options.single) op.limit = 1;
+ // Have we specified collation
+ decorateWithCollation(finalOptions, self, options);
+
// Execute the remove
self.s.topology.remove(self.s.namespace, [op], finalOptions, function(err, result) {
if(callback == null) return;
@@ -1410,6 +1438,9 @@ var rename = function(self, newName, opt, callback) {
var dropTarget = typeof opt.dropTarget == 'boolean' ? opt.dropTarget : false;
var cmd = {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, opt);
+
// Execute against admin
self.s.db.admin().command(cmd, opt, function(err, doc) {
if(err) return handleCallback(callback, err, null);
@@ -1436,10 +1467,10 @@ define.classMethod('rename', {callback: true, promise:true});
Collection.prototype.drop = function(options, callback) {
var self = this;
if(typeof options == 'function') callback = options, options = {};
- options = options | {};
+ options = options || {};
// Execute using callback
- if(typeof callback == 'function') return self.s.db.dropCollection(self.s.name, callback);
+ if(typeof callback == 'function') return self.s.db.dropCollection(self.s.name, options, callback);
// Return a Promise
return new this.s.promiseLibrary(function(resolve, reject) {
self.s.db.dropCollection(self.s.name, options, function(err, r) {
@@ -1589,11 +1620,18 @@ Collection.prototype.createIndexes = function(indexSpecs, callback) {
}
var createIndexes = function(self, indexSpecs, callback) {
+ var capabilities = self.s.topology.capabilities();
+
// Ensure we generate the correct name if the parameter is not set
for(var i = 0; i < indexSpecs.length; i++) {
if(indexSpecs[i].name == null) {
var keys = [];
+ // Did the user pass in a collation, check if our write server supports it
+ if(indexSpecs[i].collation && capabilities && !capabilities.commandsTakeCollation) {
+ return callback(new MongoError(f('server/primary/mongos does not support collation')));
+ }
+
for(var name in indexSpecs[i].key) {
keys.push(f('%s_%s', name, indexSpecs[i].key[name]));
}
@@ -1645,7 +1683,10 @@ Collection.prototype.dropIndex = function(indexName, options, callback) {
var dropIndex = function(self, indexName, options, callback) {
// Delete index command
- var cmd = {'deleteIndexes':self.s.name, 'index':indexName};
+ var cmd = {'dropIndexes':self.s.name, 'index':indexName};
+
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, options);
// Execute command
self.s.db.command(cmd, options, function(err, result) {
@@ -1663,11 +1704,15 @@ define.classMethod('dropIndex', {callback: true, promise:true});
* @param {Collection~resultCallback} [callback] The command result callback
* @return {Promise} returns Promise if no callback passed
*/
-Collection.prototype.dropIndexes = function(callback) {
+Collection.prototype.dropIndexes = function(options, callback) {
var self = this;
+ // Do we have options
+ if(typeof options == 'function') callback = options, options = {};
+ options = options || {};
+
// Execute using callback
- if(typeof callback == 'function') return dropIndexes(self, callback);
+ if(typeof callback == 'function') return dropIndexes(self, options, callback);
// Return a Promise
return new this.s.promiseLibrary(function(resolve, reject) {
@@ -1678,8 +1723,8 @@ Collection.prototype.dropIndexes = function(callback) {
});
}
-var dropIndexes = function(self, callback) {
- self.dropIndex('*', function (err, result) {
+var dropIndexes = function(self, options, callback) {
+ self.dropIndex('*', options, function(err, result) {
if(err) return handleCallback(callback, err, false);
handleCallback(callback, null, true);
});
@@ -1726,6 +1771,9 @@ var reIndex = function(self, options, callback) {
// Reindex
var cmd = {'reIndex':self.s.name};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(cmd, self, options);
+
// Execute the command
self.s.db.command(cmd, options, function(err, result) {
if(callback == null) return;
@@ -1760,25 +1808,20 @@ Collection.prototype.listIndexes = function(options) {
throw new MongoError('cannot connect to server');
}
- // console.log("!!!!!!!!!!!!!! HEY 0")
// We have a list collections command
if(this.s.topology.capabilities().hasListIndexesCommand) {
- // console.log("!!!!!!!!!!!!!! HEY 0:1")
// Cursor options
var cursor = options.batchSize ? {batchSize: options.batchSize} : {}
// Build the command
var command = { listIndexes: this.s.name, cursor: cursor };
- // console.log("!!!!!!!!!!!!!! HEY 0:2")
// Execute the cursor
var cursor = this.s.topology.cursor(f('%s.$cmd', this.s.dbName), command, options);
// Do we have a readPreference, apply it
if(options.readPreference) cursor.setReadPreference(options.readPreference);
- // console.log("!!!!!!!!!!!!!! HEY 0:3")
// Return the cursor
return cursor;
}
- // console.log("!!!!!!!!!!!!!! HEY 1")
// Get the namespace
var ns = f('%s.system.indexes', this.s.dbName);
// Get the query
@@ -1981,6 +2024,9 @@ var count = function(self, query, options, callback) {
cmd.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(cmd, self, options);
+
// Execute command
self.s.db.command(cmd, options, function(err, result) {
if(err) return handleCallback(callback, err);
@@ -2042,6 +2088,9 @@ var distinct = function(self, key, query, options, callback) {
cmd.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(cmd, self, options);
+
// Execute the command
self.s.db.command(cmd, options, function(err, result) {
if(err) return handleCallback(callback, err);
@@ -2400,6 +2449,9 @@ var findAndModify = function(self, query, sort, doc, options, callback) {
queryObject.bypassDocumentValidation = finalOptions.bypassDocumentValidation;
}
+ // Have we specified collation
+ decorateWithCollation(queryObject, self, options);
+
// Execute the command
self.s.db.command(queryObject
, options, function(err, result) {
@@ -2452,6 +2504,35 @@ var findAndRemove = function(self, query, sort, options, callback) {
define.classMethod('findAndRemove', {callback: true, promise:true});
+function decorateWithWriteConcern(command, self, options) {
+ // Do we support collation 3.4 and higher
+ var capabilities = self.s.topology.capabilities();
+ // Do we support write concerns 3.4 and higher
+ if(capabilities && capabilities.commandsTakeWriteConcern) {
+ // Get the write concern settings
+ var finalOptions = writeConcern(shallowClone(options), self.s.db, self, options);
+ // Add the write concern to the command
+ if(finalOptions.writeConcern) {
+ command.writeConcern = finalOptions.writeConcern;
+ }
+ }
+}
+
+function decorateWithCollation(command, self, options) {
+ // Do we support collation 3.4 and higher
+ var capabilities = self.s.topology.capabilities();
+ // Do we support write concerns 3.4 and higher
+ if(capabilities && capabilities.commandsTakeCollation) {
+ if(options.collation && typeof options.collation == 'object') {
+ command.collation = options.collation;
+ } else if(self.s.collation && typeof self.s.collation == 'object') {
+ command.collation = self.s.collation;
+ } else if(self.s.db.s.collation && typeof self.s.db.s.collation == 'object') {
+ command.collation = self.s.db.s.collation;
+ }
+ }
+}
+
/**
* Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2
* @method
@@ -2469,6 +2550,7 @@ define.classMethod('findAndRemove', {callback: true, promise:true});
*/
Collection.prototype.aggregate = function(pipeline, options, callback) {
var self = this;
+
if(Array.isArray(pipeline)) {
// Set up callback if one is provided
if(typeof options == 'function') {
@@ -2510,6 +2592,11 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
// Build the command
var command = { aggregate : this.s.name, pipeline : pipeline};
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(command, self, options);
+ // Have we specified collation
+ decorateWithCollation(command, self, options);
+
// If we have bypassDocumentValidation set
if(typeof options.bypassDocumentValidation == 'boolean') {
command.bypassDocumentValidation = options.bypassDocumentValidation;
@@ -2743,6 +2830,9 @@ var geoNear = function(self, x, y, point, options, callback) {
commandObject.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(commandObject, self, options);
+
// Execute the command
self.s.db.command(commandObject, options, function (err, res) {
if(err) return handleCallback(callback, err);
@@ -2952,6 +3042,9 @@ var group = function(self, keys, condition, initial, reduce, finalize, command,
selector.readConcern = self.s.readConcern;
}
+ // Have we specified collation
+ decorateWithCollation(selector, self, options);
+
// Execute command
self.s.db.command(selector, options, function(err, result) {
if(err) return handleCallback(callback, err, null);
@@ -3085,7 +3178,10 @@ var mapReduce = function(self, map, reduce, options, callback) {
// If we have a read preference and inline is not set as output fail hard
if((options.readPreference != false && options.readPreference != 'primary')
&& options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) {
+ // Force readPreference to primary
options.readPreference = 'primary';
+ // Decorate command with writeConcern if supported
+ decorateWithWriteConcern(mapCommandHash, self, options);
} else if(self.s.readConcern) {
mapCommandHash.readConcern = self.s.readConcern;
}
@@ -3095,6 +3191,9 @@ var mapReduce = function(self, map, reduce, options, callback) {
mapCommandHash.bypassDocumentValidation = options.bypassDocumentValidation;
}
+ // Have we specified collation
+ decorateWithCollation(mapCommandHash, self, options);
+
// Execute command
self.s.db.command(mapCommandHash, {readPreference:options.readPreference}, function (err, result) {
if(err) return handleCallback(callback, err);
@@ -3205,18 +3304,18 @@ var getReadPreference = function(self, options, db, coll) {
r = options.readPreference
} else if(self.s.readPreference) {
r = self.s.readPreference
- } else if(db.readPreference) {
- r = db.readPreference;
+ } else if(db.s.readPreference) {
+ r = db.s.readPreference;
}
if(r instanceof ReadPreference) {
- options.readPreference = new CoreReadPreference(r.mode, r.tags);
+ options.readPreference = new CoreReadPreference(r.mode, r.tags, {maxStalenessMS: r.maxStalenessMS});
} else if(typeof r == 'string') {
options.readPreference = new CoreReadPreference(r);
} else if(r && !(r instanceof ReadPreference) && typeof r == 'object') {
var mode = r.mode || r.preference;
if (mode && typeof mode == 'string') {
- options.readPreference = new CoreReadPreference(mode, r.tags);
+ options.readPreference = new CoreReadPreference(mode, r.tags, {maxStalenessMS: r.maxStalenessMS});
}
}
@@ -3227,6 +3326,7 @@ var testForFields = {
limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1
, numberOfRetries: 1, awaitdata: 1, awaitData: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1
, comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1, connection: 1, maxTimeMS: 1, transforms: 1
+ , collation: 1
}
module.exports = Collection;