Skip to content

Commit

Permalink
feat: always use optimized findOrCreate
Browse files Browse the repository at this point in the history
closes: #725
Signed-off-by: Rifa Achrinza <[email protected]>
  • Loading branch information
achrinza committed Sep 17, 2024
1 parent df55d72 commit c7f1148
Showing 1 changed file with 90 additions and 89 deletions.
179 changes: 90 additions & 89 deletions lib/mongodb.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.')

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

This line has a length of 129. Maximum allowed is 120

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Expected indentation of 4 spaces but found 6

Check failure on line 200 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon
}

if (this.settings.enableGeoIndexing === true) {
MongoDB.prototype.buildNearFilter = buildNearFilter;
} else {
Expand Down Expand Up @@ -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);
}
},
);
}

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

Check failure on line 1599 in lib/mongodb.js

View workflow job for this annotation

GitHub Actions / Code Lint

Missing semicolon

/**
* Transform db data to model entity
*
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit c7f1148

Please sign in to comment.