diff options
Diffstat (limited to 'node_modules/mongodb/lib/collection.js')
| -rw-r--r-- | node_modules/mongodb/lib/collection.js | 146 |
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; |
