Cleanup
This commit is contained in:
234
node_modules/mongodb/lib/bulk/common.js
generated
vendored
234
node_modules/mongodb/lib/bulk/common.js
generated
vendored
@@ -5,12 +5,15 @@ const MongoError = require('../core').MongoError;
|
||||
const ObjectID = require('../core').BSON.ObjectID;
|
||||
const BSON = require('../core').BSON;
|
||||
const MongoWriteConcernError = require('../core').MongoWriteConcernError;
|
||||
const emitWarningOnce = require('../utils').emitWarningOnce;
|
||||
const toError = require('../utils').toError;
|
||||
const handleCallback = require('../utils').handleCallback;
|
||||
const applyRetryableWrites = require('../utils').applyRetryableWrites;
|
||||
const applyWriteConcern = require('../utils').applyWriteConcern;
|
||||
const executeLegacyOperation = require('../utils').executeLegacyOperation;
|
||||
const isPromiseLike = require('../utils').isPromiseLike;
|
||||
const hasAtomicOperators = require('../utils').hasAtomicOperators;
|
||||
const maxWireVersion = require('../core/utils').maxWireVersion;
|
||||
|
||||
// Error codes
|
||||
const WRITE_CONCERN_ERROR = 64;
|
||||
@@ -54,6 +57,9 @@ class Batch {
|
||||
}
|
||||
}
|
||||
|
||||
const kUpsertedIds = Symbol('upsertedIds');
|
||||
const kInsertedIds = Symbol('insertedIds');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* The result of a bulk write.
|
||||
@@ -66,6 +72,60 @@ class BulkWriteResult {
|
||||
*/
|
||||
constructor(bulkResult) {
|
||||
this.result = bulkResult;
|
||||
this[kUpsertedIds] = undefined;
|
||||
this[kInsertedIds] = undefined;
|
||||
}
|
||||
|
||||
/** Number of documents inserted. */
|
||||
get insertedCount() {
|
||||
return typeof this.result.nInserted !== 'number' ? 0 : this.result.nInserted;
|
||||
}
|
||||
/** Number of documents matched for update. */
|
||||
get matchedCount() {
|
||||
return typeof this.result.nMatched !== 'number' ? 0 : this.result.nMatched;
|
||||
}
|
||||
/** Number of documents modified. */
|
||||
get modifiedCount() {
|
||||
return typeof this.result.nModified !== 'number' ? 0 : this.result.nModified;
|
||||
}
|
||||
/** Number of documents deleted. */
|
||||
get deletedCount() {
|
||||
return typeof this.result.nRemoved !== 'number' ? 0 : this.result.nRemoved;
|
||||
}
|
||||
/** Number of documents upserted. */
|
||||
get upsertedCount() {
|
||||
return !this.result.upserted ? 0 : this.result.upserted.length;
|
||||
}
|
||||
|
||||
/** Upserted document generated Id's, hash key is the index of the originating operation */
|
||||
get upsertedIds() {
|
||||
if (this[kUpsertedIds]) {
|
||||
return this[kUpsertedIds];
|
||||
}
|
||||
|
||||
this[kUpsertedIds] = {};
|
||||
for (const doc of this.result.upserted || []) {
|
||||
this[kUpsertedIds][doc.index] = doc._id;
|
||||
}
|
||||
return this[kUpsertedIds];
|
||||
}
|
||||
|
||||
/** Inserted document generated Id's, hash key is the index of the originating operation */
|
||||
get insertedIds() {
|
||||
if (this[kInsertedIds]) {
|
||||
return this[kInsertedIds];
|
||||
}
|
||||
|
||||
this[kInsertedIds] = {};
|
||||
for (const doc of this.result.insertedIds || []) {
|
||||
this[kInsertedIds][doc.index] = doc._id;
|
||||
}
|
||||
return this[kInsertedIds];
|
||||
}
|
||||
|
||||
/** The number of inserted documents @type {number} */
|
||||
get n() {
|
||||
return this.result.insertedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,6 +414,15 @@ class WriteError {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the number to a Long or returns it.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
function longOrConvert(value) {
|
||||
return typeof value === 'number' ? Long.fromNumber(value) : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges results into shared data structure
|
||||
* @ignore
|
||||
@@ -385,42 +454,37 @@ function mergeBatchResults(batch, bulkResult, err, result) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Deal with opTime if available
|
||||
// The server write command specification states that lastOp is an optional
|
||||
// mongod only field that has a type of timestamp. Across various scarce specs
|
||||
// where opTime is mentioned, it is an "opaque" object that can have a "ts" and
|
||||
// "t" field with Timestamp and Long as their types respectively.
|
||||
// The "lastOp" field of the bulk write result is never mentioned in the driver
|
||||
// specifications or the bulk write spec, so we should probably just keep its
|
||||
// value consistent since it seems to vary.
|
||||
// See: https://github.com/mongodb/specifications/blob/master/source/driver-bulk-update.rst#results-object
|
||||
if (result.opTime || result.lastOp) {
|
||||
const opTime = result.lastOp || result.opTime;
|
||||
let lastOpTS = null;
|
||||
let lastOpT = null;
|
||||
let opTime = result.lastOp || result.opTime;
|
||||
|
||||
// We have a time stamp
|
||||
if (opTime && opTime._bsontype === 'Timestamp') {
|
||||
if (bulkResult.lastOp == null) {
|
||||
bulkResult.lastOp = opTime;
|
||||
} else if (opTime.greaterThan(bulkResult.lastOp)) {
|
||||
bulkResult.lastOp = opTime;
|
||||
}
|
||||
// If the opTime is a Timestamp, convert it to a consistent format to be
|
||||
// able to compare easily. Converting to the object from a timestamp is
|
||||
// much more straightforward than the other direction.
|
||||
if (opTime._bsontype === 'Timestamp') {
|
||||
opTime = { ts: opTime, t: Long.ZERO };
|
||||
}
|
||||
|
||||
// If there's no lastOp, just set it.
|
||||
if (!bulkResult.lastOp) {
|
||||
bulkResult.lastOp = opTime;
|
||||
} else {
|
||||
// Existing TS
|
||||
if (bulkResult.lastOp) {
|
||||
lastOpTS =
|
||||
typeof bulkResult.lastOp.ts === 'number'
|
||||
? Long.fromNumber(bulkResult.lastOp.ts)
|
||||
: bulkResult.lastOp.ts;
|
||||
lastOpT =
|
||||
typeof bulkResult.lastOp.t === 'number'
|
||||
? Long.fromNumber(bulkResult.lastOp.t)
|
||||
: bulkResult.lastOp.t;
|
||||
}
|
||||
|
||||
// Current OpTime TS
|
||||
const opTimeTS = typeof opTime.ts === 'number' ? Long.fromNumber(opTime.ts) : opTime.ts;
|
||||
const opTimeT = typeof opTime.t === 'number' ? Long.fromNumber(opTime.t) : opTime.t;
|
||||
|
||||
// Compare the opTime's
|
||||
if (bulkResult.lastOp == null) {
|
||||
bulkResult.lastOp = opTime;
|
||||
} else if (opTimeTS.greaterThan(lastOpTS)) {
|
||||
// First compare the ts values and set if the opTimeTS value is greater.
|
||||
const lastOpTS = longOrConvert(bulkResult.lastOp.ts);
|
||||
const opTimeTS = longOrConvert(opTime.ts);
|
||||
if (opTimeTS.greaterThan(lastOpTS)) {
|
||||
bulkResult.lastOp = opTime;
|
||||
} else if (opTimeTS.equals(lastOpTS)) {
|
||||
// If the ts values are equal, then compare using the t values.
|
||||
const lastOpT = longOrConvert(bulkResult.lastOp.t);
|
||||
const opTimeT = longOrConvert(opTime.t);
|
||||
if (opTimeT.greaterThan(lastOpT)) {
|
||||
bulkResult.lastOp = opTime;
|
||||
}
|
||||
@@ -569,6 +633,35 @@ class BulkWriteError extends MongoError {
|
||||
this.name = 'BulkWriteError';
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
/** Number of documents inserted. */
|
||||
get insertedCount() {
|
||||
return this.result.insertedCount;
|
||||
}
|
||||
/** Number of documents matched for update. */
|
||||
get matchedCount() {
|
||||
return this.result.matchedCount;
|
||||
}
|
||||
/** Number of documents modified. */
|
||||
get modifiedCount() {
|
||||
return this.result.modifiedCount;
|
||||
}
|
||||
/** Number of documents deleted. */
|
||||
get deletedCount() {
|
||||
return this.result.deletedCount;
|
||||
}
|
||||
/** Number of documents upserted. */
|
||||
get upsertedCount() {
|
||||
return this.result.upsertedCount;
|
||||
}
|
||||
/** Inserted document generated Id's, hash key is the index of the originating operation */
|
||||
get insertedIds() {
|
||||
return this.result.insertedIds;
|
||||
}
|
||||
/** Upserted document generated Id's, hash key is the index of the originating operation */
|
||||
get upsertedIds() {
|
||||
return this.result.upsertedIds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -641,6 +734,10 @@ class FindOperators {
|
||||
document.hint = updateDocument.hint;
|
||||
}
|
||||
|
||||
if (!hasAtomicOperators(updateDocument)) {
|
||||
throw new TypeError('Update document requires atomic operators');
|
||||
}
|
||||
|
||||
// Clear out current Op
|
||||
this.s.currentOp = null;
|
||||
return this.s.options.addToOperationsList(this, UPDATE, document);
|
||||
@@ -650,12 +747,33 @@ class FindOperators {
|
||||
* Add a replace one operation to the bulk operation
|
||||
*
|
||||
* @method
|
||||
* @param {object} updateDocument the new document to replace the existing one with
|
||||
* @param {object} replacement the new document to replace the existing one with
|
||||
* @throws {MongoError} If operation cannot be added to bulk write
|
||||
* @return {OrderedBulkOperation|UnorderedBulkOperation} A reference to the parent BulkOperation
|
||||
*/
|
||||
replaceOne(updateDocument) {
|
||||
this.updateOne(updateDocument);
|
||||
replaceOne(replacement) {
|
||||
// Perform upsert
|
||||
const upsert = typeof this.s.currentOp.upsert === 'boolean' ? this.s.currentOp.upsert : false;
|
||||
|
||||
// Establish the update command
|
||||
const document = {
|
||||
q: this.s.currentOp.selector,
|
||||
u: replacement,
|
||||
multi: false,
|
||||
upsert: upsert
|
||||
};
|
||||
|
||||
if (replacement.hint) {
|
||||
document.hint = replacement.hint;
|
||||
}
|
||||
|
||||
if (hasAtomicOperators(replacement)) {
|
||||
throw new TypeError('Replacement document must not use atomic operators');
|
||||
}
|
||||
|
||||
// Clear out current Op
|
||||
this.s.currentOp = null;
|
||||
return this.s.options.addToOperationsList(this, UPDATE, document);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -710,15 +828,19 @@ class FindOperators {
|
||||
|
||||
/**
|
||||
* backwards compatability for deleteOne
|
||||
* @deprecated
|
||||
*/
|
||||
removeOne() {
|
||||
emitWarningOnce('bulk operation `removeOne` has been deprecated, please use `deleteOne`');
|
||||
return this.deleteOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* backwards compatability for delete
|
||||
* @deprecated
|
||||
*/
|
||||
remove() {
|
||||
emitWarningOnce('bulk operation `remove` has been deprecated, please use `delete`');
|
||||
return this.delete();
|
||||
}
|
||||
}
|
||||
@@ -943,6 +1065,12 @@ class BulkOperationBase {
|
||||
|
||||
// Crud spec update format
|
||||
if (op.updateOne || op.updateMany || op.replaceOne) {
|
||||
if (op.replaceOne && hasAtomicOperators(op[key].replacement)) {
|
||||
throw new TypeError('Replacement document must not use atomic operators');
|
||||
} else if ((op.updateOne || op.updateMany) && !hasAtomicOperators(op[key].update)) {
|
||||
throw new TypeError('Update document requires atomic operators');
|
||||
}
|
||||
|
||||
const multi = op.updateOne || op.replaceOne ? false : true;
|
||||
const operation = {
|
||||
q: op[key].filter,
|
||||
@@ -960,7 +1088,15 @@ class BulkOperationBase {
|
||||
} else {
|
||||
if (op[key].upsert) operation.upsert = true;
|
||||
}
|
||||
if (op[key].arrayFilters) operation.arrayFilters = op[key].arrayFilters;
|
||||
if (op[key].arrayFilters) {
|
||||
// TODO: this check should be done at command construction against a connection, not a topology
|
||||
if (maxWireVersion(this.s.topology) < 6) {
|
||||
throw new TypeError('arrayFilters are only supported on MongoDB 3.6+');
|
||||
}
|
||||
|
||||
operation.arrayFilters = op[key].arrayFilters;
|
||||
}
|
||||
|
||||
return this.s.options.addToOperationsList(this, UPDATE, operation);
|
||||
}
|
||||
|
||||
@@ -979,6 +1115,9 @@ class BulkOperationBase {
|
||||
if (op.deleteOne || op.deleteMany) {
|
||||
const limit = op.deleteOne ? 1 : 0;
|
||||
const operation = { q: op[key].filter, limit: limit };
|
||||
if (op[key].hint) {
|
||||
operation.hint = op[key].hint;
|
||||
}
|
||||
if (this.isOrdered) {
|
||||
if (op.collation) operation.collation = op.collation;
|
||||
}
|
||||
@@ -997,6 +1136,9 @@ class BulkOperationBase {
|
||||
}
|
||||
|
||||
if (op.insertMany) {
|
||||
emitWarningOnce(
|
||||
'bulk operation `insertMany` has been deprecated; use multiple `insertOne` ops instead'
|
||||
);
|
||||
for (let i = 0; i < op.insertMany.length; i++) {
|
||||
if (forceServerObjectId !== true && op.insertMany[i]._id == null)
|
||||
op.insertMany[i]._id = new ObjectID();
|
||||
@@ -1038,8 +1180,11 @@ class BulkOperationBase {
|
||||
* @param {function} callback
|
||||
*/
|
||||
bulkExecute(_writeConcern, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
}
|
||||
|
||||
const finalOptions = Object.assign({}, this.s.options, options);
|
||||
|
||||
if (typeof _writeConcern === 'function') {
|
||||
callback = _writeConcern;
|
||||
@@ -1065,7 +1210,7 @@ class BulkOperationBase {
|
||||
const emptyBatchError = toError('Invalid Operation, no operations specified');
|
||||
return this._handleEarlyError(emptyBatchError, callback);
|
||||
}
|
||||
return { options, callback };
|
||||
return { options: finalOptions, callback };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1081,10 +1226,11 @@ class BulkOperationBase {
|
||||
* @method
|
||||
* @param {WriteConcern} [_writeConcern] Optional write concern. Can also be specified through options.
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {(number|string)} [options.w] The write concern.
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {boolean} [options.fsync=false] Specify a file sync write concern.
|
||||
* @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
|
||||
* @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
|
||||
* @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
|
||||
* @param {boolean} [options.fsync=false] **Deprecated** Specify a file sync write concern. Use writeConcern instead.
|
||||
* @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
|
||||
* @param {BulkOperationBase~resultCallback} [callback] A callback that will be invoked when bulkWrite finishes/errors
|
||||
* @throws {MongoError} Throws error if the bulk object has already been executed
|
||||
* @throws {MongoError} Throws error if the bulk object does not have any operations
|
||||
@@ -1245,9 +1391,11 @@ Object.defineProperty(BulkOperationBase.prototype, 'length', {
|
||||
module.exports = {
|
||||
Batch,
|
||||
BulkOperationBase,
|
||||
mergeBatchResults,
|
||||
bson,
|
||||
INSERT: INSERT,
|
||||
UPDATE: UPDATE,
|
||||
REMOVE: REMOVE,
|
||||
BulkWriteError
|
||||
BulkWriteError,
|
||||
BulkWriteResult
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user