Skip to content

Commit c7f1148

Browse files
committed
feat: always use optimized findOrCreate
closes: #725 Signed-off-by: Rifa Achrinza <[email protected]>
1 parent df55d72 commit c7f1148

File tree

1 file changed

+90
-89
lines changed

1 file changed

+90
-89
lines changed

lib/mongodb.js

+90-89
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,9 @@ function MongoDB(settings, dataSource) {
197197
this.settings.enableOptimizedfindOrCreate === true ||
198198
this.settings.enableOptimizedFindOrCreate === true
199199
) {
200-
MongoDB.prototype.findOrCreate = optimizedFindOrCreate;
200+
debug('Optimized findOrCreate is enabled by default, and the enableOptimizedFindOrCreate setting is ignored since v7.0.0.')
201201
}
202+
202203
if (this.settings.enableGeoIndexing === true) {
203204
MongoDB.prototype.buildNearFilter = buildNearFilter;
204205
} else {
@@ -1509,6 +1510,94 @@ MongoDB.prototype.all = function all(modelName, filter, options, callback) {
15091510
}
15101511
};
15111512

1513+
/**
1514+
* Find a matching model instances by the filter or create a new instance
1515+
*
1516+
* Only supported on mongodb 2.6+
1517+
*
1518+
* @param {String} modelName The model name
1519+
* @param {Object} data The model instance data
1520+
* @param {Object} filter The filter
1521+
* @param {Function} [callback] The callback function
1522+
*/
1523+
MongoDB.prototype.findOrCreate = function findOrCreate(modelName, filter, data, options, callback) {
1524+
const self = this;
1525+
if (self.debug) {
1526+
debug('findOrCreate', modelName, filter, data);
1527+
}
1528+
1529+
if (!callback) callback = options;
1530+
1531+
const idValue = self.getIdValue(modelName, data);
1532+
const idName = self.idName(modelName);
1533+
1534+
if (idValue == null) {
1535+
delete data[idName]; // Allow MongoDB to generate the id
1536+
} else {
1537+
const oid = self.coerceId(modelName, idValue, options); // Is it an Object ID?
1538+
data._id = oid; // Set it to _id
1539+
if (idName !== '_id') {
1540+
delete data[idName];
1541+
}
1542+
}
1543+
1544+
filter = filter || {};
1545+
let query = {};
1546+
if (filter.where) {
1547+
if (filter.where[idName]) {
1548+
let id = filter.where[idName];
1549+
delete filter.where[idName];
1550+
id = self.coerceId(modelName, id, options);
1551+
filter.where._id = id;
1552+
}
1553+
query = self.buildWhere(modelName, filter.where, options);
1554+
}
1555+
1556+
const sort = self.buildSort(modelName, filter.order, options);
1557+
1558+
const projection = fieldsArrayToObj(filter.fields);
1559+
1560+
this.collection(modelName).findOneAndUpdate(
1561+
query,
1562+
{$setOnInsert: data},
1563+
{projection: projection, sort: sort, upsert: true},
1564+
function(err, result) {
1565+
if (self.debug) {
1566+
debug('findOrCreate.callback', modelName, filter, err, result);
1567+
}
1568+
if (err) {
1569+
return callback(err);
1570+
}
1571+
1572+
let value = result.value;
1573+
const created = !!result.lastErrorObject.upserted;
1574+
1575+
if (created && (value == null || Object.keys(value).length === 0)) {
1576+
value = data;
1577+
self.setIdValue(modelName, value, result.lastErrorObject.upserted);
1578+
} else {
1579+
value = self.fromDatabase(modelName, value);
1580+
self.setIdValue(modelName, value, value._id);
1581+
}
1582+
1583+
if (value && idName !== '_id') {
1584+
delete value._id;
1585+
}
1586+
1587+
if (filter && filter.include) {
1588+
self._models[modelName].model.include([value], filter.include, function(
1589+
err,
1590+
data,
1591+
) {
1592+
callback(err, data[0], created);
1593+
});
1594+
} else {
1595+
callback(null, value, created);
1596+
}
1597+
},
1598+
);
1599+
}
1600+
15121601
/**
15131602
* Transform db data to model entity
15141603
*
@@ -2265,94 +2354,6 @@ function sanitizeFilter(filter, options) {
22652354

22662355
exports.sanitizeFilter = sanitizeFilter;
22672356

2268-
/**
2269-
* Find a matching model instances by the filter or create a new instance
2270-
*
2271-
* Only supported on mongodb 2.6+
2272-
*
2273-
* @param {String} modelName The model name
2274-
* @param {Object} data The model instance data
2275-
* @param {Object} filter The filter
2276-
* @param {Function} [callback] The callback function
2277-
*/
2278-
function optimizedFindOrCreate(modelName, filter, data, options, callback) {
2279-
const self = this;
2280-
if (self.debug) {
2281-
debug('findOrCreate', modelName, filter, data);
2282-
}
2283-
2284-
if (!callback) callback = options;
2285-
2286-
const idValue = self.getIdValue(modelName, data);
2287-
const idName = self.idName(modelName);
2288-
2289-
if (idValue == null) {
2290-
delete data[idName]; // Allow MongoDB to generate the id
2291-
} else {
2292-
const oid = self.coerceId(modelName, idValue, options); // Is it an Object ID?
2293-
data._id = oid; // Set it to _id
2294-
if (idName !== '_id') {
2295-
delete data[idName];
2296-
}
2297-
}
2298-
2299-
filter = filter || {};
2300-
let query = {};
2301-
if (filter.where) {
2302-
if (filter.where[idName]) {
2303-
let id = filter.where[idName];
2304-
delete filter.where[idName];
2305-
id = self.coerceId(modelName, id, options);
2306-
filter.where._id = id;
2307-
}
2308-
query = self.buildWhere(modelName, filter.where, options);
2309-
}
2310-
2311-
const sort = self.buildSort(modelName, filter.order, options);
2312-
2313-
const projection = fieldsArrayToObj(filter.fields);
2314-
2315-
this.collection(modelName).findOneAndUpdate(
2316-
query,
2317-
{$setOnInsert: data},
2318-
{projection: projection, sort: sort, upsert: true},
2319-
function(err, result) {
2320-
if (self.debug) {
2321-
debug('findOrCreate.callback', modelName, filter, err, result);
2322-
}
2323-
if (err) {
2324-
return callback(err);
2325-
}
2326-
2327-
let value = result.value;
2328-
const created = !!result.lastErrorObject.upserted;
2329-
2330-
if (created && (value == null || Object.keys(value).length === 0)) {
2331-
value = data;
2332-
self.setIdValue(modelName, value, result.lastErrorObject.upserted);
2333-
} else {
2334-
value = self.fromDatabase(modelName, value);
2335-
self.setIdValue(modelName, value, value._id);
2336-
}
2337-
2338-
if (value && idName !== '_id') {
2339-
delete value._id;
2340-
}
2341-
2342-
if (filter && filter.include) {
2343-
self._models[modelName].model.include([value], filter.include, function(
2344-
err,
2345-
data,
2346-
) {
2347-
callback(err, data[0], created);
2348-
});
2349-
} else {
2350-
callback(null, value, created);
2351-
}
2352-
},
2353-
);
2354-
}
2355-
23562357
/**
23572358
* @param {*} data Plain Data Object for the matching property definition(s)
23582359
* @param {*} modelCtor Model constructor

0 commit comments

Comments
 (0)