Skip to content

Commit d03335e

Browse files
jdaprahamian
authored andcommitted
feat(collection): add colleciton level document mapping/unmapping
1 parent 9854850 commit d03335e

File tree

3 files changed

+410
-33
lines changed

3 files changed

+410
-33
lines changed

lib/collection.js

+43-33
Original file line numberDiff line numberDiff line change
@@ -378,14 +378,14 @@ Collection.prototype.find = function(query, options, callback) {
378378
// Decorate find command with collation options
379379
decorateWithCollation(findCommand, this, options);
380380

381-
// Create the cursor
382-
if (typeof callback === 'function')
383-
return handleCallback(
384-
callback,
385-
null,
386-
this.s.topology.cursor(this.s.namespace, findCommand, newOptions)
387-
);
388-
return this.s.topology.cursor(this.s.namespace, findCommand, newOptions);
381+
const cursor = this.s.topology.cursor(this.s.namespace, findCommand, newOptions);
382+
383+
// automatically call map on the cursor if the map option is set
384+
if (typeof this.s.options.map === 'function') {
385+
cursor.map(this.s.options.map);
386+
}
387+
388+
return typeof callback === 'function' ? handleCallback(callback, null, cursor) : cursor;
389389
};
390390

391391
/**
@@ -491,19 +491,7 @@ Collection.prototype.insertMany = function(docs, options, callback) {
491491
// If keep going set unordered
492492
options['serializeFunctions'] = options['serializeFunctions'] || self.s.serializeFunctions;
493493

494-
// Set up the force server object id
495-
var forceServerObjectId =
496-
typeof options.forceServerObjectId === 'boolean'
497-
? options.forceServerObjectId
498-
: self.s.db.options.forceServerObjectId;
499-
500-
// Do we want to force the server to assign the _id key
501-
if (forceServerObjectId !== true) {
502-
// Add _id if not specified
503-
for (var i = 0; i < docs.length; i++) {
504-
if (docs[i]._id == null) docs[i]._id = self.s.pkFactory.createPk();
505-
}
506-
}
494+
docs = prepareDocs(this, docs, options);
507495

508496
// Generate the bulk write operations
509497
var operations = [
@@ -683,18 +671,7 @@ var insertDocuments = function(self, docs, options, callback) {
683671
if (finalOptions.keepGoing === true) finalOptions.ordered = false;
684672
finalOptions['serializeFunctions'] = options['serializeFunctions'] || self.s.serializeFunctions;
685673

686-
// Set up the force server object id
687-
var forceServerObjectId =
688-
typeof options.forceServerObjectId === 'boolean'
689-
? options.forceServerObjectId
690-
: self.s.db.options.forceServerObjectId;
691-
692-
// Add _id if not specified
693-
if (forceServerObjectId !== true) {
694-
for (var i = 0; i < docs.length; i++) {
695-
if (docs[i]._id === void 0) docs[i]._id = self.s.pkFactory.createPk();
696-
}
697-
}
674+
docs = prepareDocs(self, docs, options);
698675

699676
// File inserts
700677
self.s.topology.insert(self.s.namespace, docs, finalOptions, function(err, result) {
@@ -909,6 +886,10 @@ Collection.prototype.replaceOne = function(filter, doc, options, callback) {
909886
options.ignoreUndefined = this.s.options.ignoreUndefined;
910887
}
911888

889+
if (typeof this.s.options.unmap === 'function') {
890+
doc = this.s.options.unmap(doc);
891+
}
892+
912893
return executeOperation(this.s.topology, replaceOne, [this, filter, doc, options, callback]);
913894
};
914895

@@ -2253,6 +2234,11 @@ var findAndModify = function(self, query, sort, doc, options, callback) {
22532234
// Execute the command
22542235
self.s.db.command(queryObject, finalOptions, function(err, result) {
22552236
if (err) return handleCallback(callback, err, null);
2237+
2238+
if (result && result.value && typeof self.s.options.map === 'function') {
2239+
result.value = self.s.options.map(result.value);
2240+
}
2241+
22562242
return handleCallback(callback, null, result);
22572243
});
22582244
};
@@ -3028,4 +3014,28 @@ var getReadPreference = function(self, options, db) {
30283014
return options;
30293015
};
30303016

3017+
// modifies documents before being inserted or updated
3018+
const prepareDocs = function(self, docs, options) {
3019+
const forceServerObjectId =
3020+
typeof options.forceServerObjectId === 'boolean'
3021+
? options.forceServerObjectId
3022+
: self.s.db.options.forceServerObjectId;
3023+
3024+
const unmap = typeof self.s.options.unmap === 'function' ? self.s.options.unmap : false;
3025+
3026+
// no need to modify the docs if server sets the ObjectId
3027+
// and unmap collection option is unset
3028+
if (forceServerObjectId === true && !unmap) {
3029+
return docs;
3030+
}
3031+
3032+
return docs.map(function(doc) {
3033+
if (forceServerObjectId !== true && doc._id == null) {
3034+
doc._id = self.s.pkFactory.createPk();
3035+
}
3036+
3037+
return unmap ? unmap(doc) : doc;
3038+
});
3039+
};
3040+
30313041
module.exports = Collection;

lib/db.js

+2
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ var collectionKeys = [
400400
* @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
401401
* @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
402402
* @param {boolean} [options.strict=false] Returns an error if the collection does not exist
403+
* @param {function} [options.map] Function to map documents returned in find, findOne, and findAndModify commands.
404+
* @param {function} [options.unmap] Function to unmap documents passed to insertOne, insertMany, and replaceOne commands.
403405
* @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
404406
* @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
405407
* @param {Db~collectionResultCallback} [callback] The collection result callback

0 commit comments

Comments
 (0)