diff --git a/lib/mongodb.js b/lib/mongodb.js index 0f11f8be4..31759e8ec 100644 --- a/lib/mongodb.js +++ b/lib/mongodb.js @@ -197,8 +197,9 @@ function MongoDB(settings, dataSource) { this.settings.enableOptimizedfindOrCreate === true || this.settings.enableOptimizedFindOrCreate === true ) { - MongoDB.prototype.findOrCreate = optimizedFindOrCreate; + debug('Optimized findOrCreate is enabled by default, and the enableOptimizedFindOrCreate setting is ignored since v7.0.0.') } + if (this.settings.enableGeoIndexing === true) { MongoDB.prototype.buildNearFilter = buildNearFilter; } else { @@ -1509,6 +1510,94 @@ MongoDB.prototype.all = function all(modelName, filter, options, callback) { } }; +/** + * Find a matching model instances by the filter or create a new instance + * + * Only supported on mongodb 2.6+ + * + * @param {String} modelName The model name + * @param {Object} data The model instance data + * @param {Object} filter The filter + * @param {Function} [callback] The callback function + */ +MongoDB.prototype.findOrCreate = function findOrCreate(modelName, filter, data, options, callback) { + const self = this; + if (self.debug) { + debug('findOrCreate', modelName, filter, data); + } + + if (!callback) callback = options; + + const idValue = self.getIdValue(modelName, data); + const idName = self.idName(modelName); + + if (idValue == null) { + delete data[idName]; // Allow MongoDB to generate the id + } else { + const oid = self.coerceId(modelName, idValue, options); // Is it an Object ID? + data._id = oid; // Set it to _id + if (idName !== '_id') { + delete data[idName]; + } + } + + filter = filter || {}; + let query = {}; + if (filter.where) { + if (filter.where[idName]) { + let id = filter.where[idName]; + delete filter.where[idName]; + id = self.coerceId(modelName, id, options); + filter.where._id = id; + } + query = self.buildWhere(modelName, filter.where, options); + } + + const sort = self.buildSort(modelName, filter.order, options); + + const projection = fieldsArrayToObj(filter.fields); + + this.collection(modelName).findOneAndUpdate( + query, + {$setOnInsert: data}, + {projection: projection, sort: sort, upsert: true}, + function(err, result) { + if (self.debug) { + debug('findOrCreate.callback', modelName, filter, err, result); + } + if (err) { + return callback(err); + } + + let value = result.value; + const created = !!result.lastErrorObject.upserted; + + if (created && (value == null || Object.keys(value).length === 0)) { + value = data; + self.setIdValue(modelName, value, result.lastErrorObject.upserted); + } else { + value = self.fromDatabase(modelName, value); + self.setIdValue(modelName, value, value._id); + } + + if (value && idName !== '_id') { + delete value._id; + } + + if (filter && filter.include) { + self._models[modelName].model.include([value], filter.include, function( + err, + data, + ) { + callback(err, data[0], created); + }); + } else { + callback(null, value, created); + } + }, + ); +} + /** * Transform db data to model entity * @@ -2265,94 +2354,6 @@ function sanitizeFilter(filter, options) { exports.sanitizeFilter = sanitizeFilter; -/** - * Find a matching model instances by the filter or create a new instance - * - * Only supported on mongodb 2.6+ - * - * @param {String} modelName The model name - * @param {Object} data The model instance data - * @param {Object} filter The filter - * @param {Function} [callback] The callback function - */ -function optimizedFindOrCreate(modelName, filter, data, options, callback) { - const self = this; - if (self.debug) { - debug('findOrCreate', modelName, filter, data); - } - - if (!callback) callback = options; - - const idValue = self.getIdValue(modelName, data); - const idName = self.idName(modelName); - - if (idValue == null) { - delete data[idName]; // Allow MongoDB to generate the id - } else { - const oid = self.coerceId(modelName, idValue, options); // Is it an Object ID? - data._id = oid; // Set it to _id - if (idName !== '_id') { - delete data[idName]; - } - } - - filter = filter || {}; - let query = {}; - if (filter.where) { - if (filter.where[idName]) { - let id = filter.where[idName]; - delete filter.where[idName]; - id = self.coerceId(modelName, id, options); - filter.where._id = id; - } - query = self.buildWhere(modelName, filter.where, options); - } - - const sort = self.buildSort(modelName, filter.order, options); - - const projection = fieldsArrayToObj(filter.fields); - - this.collection(modelName).findOneAndUpdate( - query, - {$setOnInsert: data}, - {projection: projection, sort: sort, upsert: true}, - function(err, result) { - if (self.debug) { - debug('findOrCreate.callback', modelName, filter, err, result); - } - if (err) { - return callback(err); - } - - let value = result.value; - const created = !!result.lastErrorObject.upserted; - - if (created && (value == null || Object.keys(value).length === 0)) { - value = data; - self.setIdValue(modelName, value, result.lastErrorObject.upserted); - } else { - value = self.fromDatabase(modelName, value); - self.setIdValue(modelName, value, value._id); - } - - if (value && idName !== '_id') { - delete value._id; - } - - if (filter && filter.include) { - self._models[modelName].model.include([value], filter.include, function( - err, - data, - ) { - callback(err, data[0], created); - }); - } else { - callback(null, value, created); - } - }, - ); -} - /** * @param {*} data Plain Data Object for the matching property definition(s) * @param {*} modelCtor Model constructor