mongodb 3.6.6 → 3.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +39 -0
- package/README.md +4 -4
- package/lib/bulk/common.js +96 -1
- package/lib/cmap/connection.js +37 -32
- package/lib/collection.js +56 -32
- package/lib/command_utils.js +124 -0
- package/lib/core/auth/mongo_credentials.js +5 -5
- package/lib/core/connection/apm.js +10 -123
- package/lib/core/connection/commands.js +11 -2
- package/lib/core/connection/connect.js +3 -0
- package/lib/core/connection/connection.js +6 -3
- package/lib/core/connection/msg.js +11 -2
- package/lib/core/connection/pool.js +6 -2
- package/lib/core/cursor.js +7 -0
- package/lib/core/error.js +2 -2
- package/lib/core/sdam/monitor.js +2 -1
- package/lib/core/sdam/server.js +8 -1
- package/lib/core/sdam/topology.js +24 -15
- package/lib/core/topologies/mongos.js +1 -0
- package/lib/core/topologies/replset.js +2 -1
- package/lib/core/topologies/server.js +7 -2
- package/lib/core/uri_parser.js +3 -1
- package/lib/core/wireprotocol/command.js +10 -5
- package/lib/core/wireprotocol/constants.js +2 -2
- package/lib/core/wireprotocol/shared.js +1 -0
- package/lib/cursor.js +12 -2
- package/lib/db.js +82 -72
- package/lib/mongo_client.js +89 -164
- package/lib/operations/bulk_write.js +0 -25
- package/lib/operations/command.js +4 -1
- package/lib/operations/command_v2.js +7 -1
- package/lib/operations/connect.js +2 -1
- package/lib/operations/db_ops.js +6 -2
- package/lib/operations/find_one_and_replace.js +8 -2
- package/lib/operations/find_one_and_update.js +8 -3
- package/lib/operations/insert_many.js +1 -5
- package/lib/topologies/mongos.js +1 -0
- package/lib/topologies/replset.js +1 -0
- package/lib/topologies/server.js +1 -0
- package/lib/url_parser.js +2 -1
- package/lib/utils.js +90 -6
- package/package.json +22 -15
package/HISTORY.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [3.6.10](https://github.com/mongodb/node-mongodb-native/compare/v3.6.9...v3.6.10) (2021-07-06)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **NODE-2035:** Exceptions thrown from awaited cursor forEach do not propagate ([#2852](https://github.com/mongodb/node-mongodb-native/issues/2852)) ([a917dfa](https://github.com/mongodb/node-mongodb-native/commit/a917dfada67859412344ed238796cf3bee243f5f))
|
|
11
|
+
* **NODE-3150:** added bsonRegExp option for v3.6 ([#2843](https://github.com/mongodb/node-mongodb-native/issues/2843)) ([e4a9a57](https://github.com/mongodb/node-mongodb-native/commit/e4a9a572427666fd1a89576dadf50b9c452e1659))
|
|
12
|
+
* **NODE-3358:** Command monitoring objects hold internal state references ([#2858](https://github.com/mongodb/node-mongodb-native/issues/2858)) ([750760c](https://github.com/mongodb/node-mongodb-native/commit/750760c324ddedb72491befde9f7aff1ceec009c))
|
|
13
|
+
* **NODE-3380:** perform retryable write checks against server ([#2861](https://github.com/mongodb/node-mongodb-native/issues/2861)) ([621677a](https://github.com/mongodb/node-mongodb-native/commit/621677a42772e0b26aa13883f57d7e42f86df43f))
|
|
14
|
+
* **NODE-3397:** report more helpful error with unsupported authMechanism in initial handshake ([#2876](https://github.com/mongodb/node-mongodb-native/issues/2876)) ([3ce148d](https://github.com/mongodb/node-mongodb-native/commit/3ce148d8fb37faea1ee056f6e9331e5282e65cd0))
|
|
15
|
+
|
|
16
|
+
### [3.6.9](https://github.com/mongodb/node-mongodb-native/compare/v3.6.8...v3.6.9) (2021-05-26)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* **NODE-3309:** remove redundant iteration of bulk write result ([#2815](https://github.com/mongodb/node-mongodb-native/issues/2815)) ([fac9610](https://github.com/mongodb/node-mongodb-native/commit/fac961086eafa0f7437576fd6af900e1f9fe22ed))
|
|
22
|
+
* fix url parsing for a mongodb+srv url that has commas in the database name ([#2789](https://github.com/mongodb/node-mongodb-native/issues/2789)) ([58c4e69](https://github.com/mongodb/node-mongodb-native/commit/58c4e693cc3a717254144d5f9bdddd8414217e97))
|
|
23
|
+
|
|
24
|
+
### [3.6.8](https://github.com/mongodb/node-mongodb-native/compare/v3.6.7...v3.6.8) (2021-05-21)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
* **cmap:** undo flipping of `beforeHandshake` flag for timeout errors ([#2813](https://github.com/mongodb/node-mongodb-native/issues/2813)) ([6e3bab3](https://github.com/mongodb/node-mongodb-native/commit/6e3bab32204ea905ab9b949edccb68556b50d382))
|
|
30
|
+
|
|
31
|
+
### [3.6.7](https://github.com/mongodb/node-mongodb-native/compare/v3.6.6...v3.6.7) (2021-05-18)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
* **docs:** removing incorrect apm docs ([#2793](https://github.com/mongodb/node-mongodb-native/issues/2793)) ([971259a](https://github.com/mongodb/node-mongodb-native/commit/971259a868a8018e90ebc2f28d151eb7af3dd50a))
|
|
37
|
+
* **NODE-3173:** Preserve sort key order for numeric string keys ([#2790](https://github.com/mongodb/node-mongodb-native/issues/2790)) ([730f43a](https://github.com/mongodb/node-mongodb-native/commit/730f43af6d9e53603af998353b720d8161426d8c))
|
|
38
|
+
* **NODE-3176:** handle errors from MessageStream ([#2774](https://github.com/mongodb/node-mongodb-native/issues/2774)) ([f1afcc4](https://github.com/mongodb/node-mongodb-native/commit/f1afcc4efbc41ce436812a6bfa22843e939ab5cf))
|
|
39
|
+
* **NODE-3192:** check clusterTime is defined before access ([#2806](https://github.com/mongodb/node-mongodb-native/issues/2806)) ([6ceace6](https://github.com/mongodb/node-mongodb-native/commit/6ceace6b245c42b8498fb1b13e7c37a97a46946d))
|
|
40
|
+
* **NODE-3252:** state transistion from DISCONNECTED ([#2807](https://github.com/mongodb/node-mongodb-native/issues/2807)) ([5d8f649](https://github.com/mongodb/node-mongodb-native/commit/5d8f6493a0ba4b525434c0868e2ae12315b4c249))
|
|
41
|
+
* **sdam:** topology no longer causes close event ([#2791](https://github.com/mongodb/node-mongodb-native/issues/2791)) ([16e7064](https://github.com/mongodb/node-mongodb-native/commit/16e70642f25954a03b91a2c2991cea96b8356de7))
|
|
42
|
+
* invalid case on writeconcern makes skip check fail ([#2773](https://github.com/mongodb/node-mongodb-native/issues/2773)) ([b1363c2](https://github.com/mongodb/node-mongodb-native/commit/b1363c26db5da5003f9db43be7e8d6e9007d45bd))
|
|
43
|
+
|
|
5
44
|
### [3.6.6](https://github.com/mongodb/node-mongodb-native/compare/v3.6.5...v3.6.6) (2021-04-06)
|
|
6
45
|
|
|
7
46
|
|
package/README.md
CHANGED
|
@@ -15,10 +15,10 @@ Check out our [beta version 4.0 here](https://github.com/mongodb/node-mongodb-na
|
|
|
15
15
|
|
|
16
16
|
| what | where |
|
|
17
17
|
| ------------- | ---------------------------------------------------- |
|
|
18
|
-
| documentation |
|
|
19
|
-
| api-doc |
|
|
18
|
+
| documentation | https://mongodb.github.io/node-mongodb-native |
|
|
19
|
+
| api-doc | https://mongodb.github.io/node-mongodb-native/3.6/api |
|
|
20
20
|
| source | https://github.com/mongodb/node-mongodb-native |
|
|
21
|
-
| mongodb |
|
|
21
|
+
| mongodb | https://www.mongodb.org |
|
|
22
22
|
|
|
23
23
|
### Bugs / Feature Requests
|
|
24
24
|
|
|
@@ -481,7 +481,7 @@ For more detailed information, see the [tutorials](docs/reference/content/tutori
|
|
|
481
481
|
|
|
482
482
|
## Next Steps
|
|
483
483
|
|
|
484
|
-
- [MongoDB Documentation](
|
|
484
|
+
- [MongoDB Documentation](https://mongodb.org)
|
|
485
485
|
- [Read about Schemas](http://learnmongodbthehardway.com)
|
|
486
486
|
- [Star us on GitHub](https://github.com/mongodb/node-mongodb-native)
|
|
487
487
|
|
package/lib/bulk/common.js
CHANGED
|
@@ -5,6 +5,7 @@ const MongoError = require('../core').MongoError;
|
|
|
5
5
|
const ObjectID = require('../core').BSON.ObjectID;
|
|
6
6
|
const BSON = require('../core').BSON;
|
|
7
7
|
const MongoWriteConcernError = require('../core').MongoWriteConcernError;
|
|
8
|
+
const emitWarningOnce = require('../utils').emitWarningOnce;
|
|
8
9
|
const toError = require('../utils').toError;
|
|
9
10
|
const handleCallback = require('../utils').handleCallback;
|
|
10
11
|
const applyRetryableWrites = require('../utils').applyRetryableWrites;
|
|
@@ -56,6 +57,9 @@ class Batch {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
const kUpsertedIds = Symbol('upsertedIds');
|
|
61
|
+
const kInsertedIds = Symbol('insertedIds');
|
|
62
|
+
|
|
59
63
|
/**
|
|
60
64
|
* @classdesc
|
|
61
65
|
* The result of a bulk write.
|
|
@@ -68,6 +72,60 @@ class BulkWriteResult {
|
|
|
68
72
|
*/
|
|
69
73
|
constructor(bulkResult) {
|
|
70
74
|
this.result = bulkResult;
|
|
75
|
+
this[kUpsertedIds] = undefined;
|
|
76
|
+
this[kInsertedIds] = undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Number of documents inserted. */
|
|
80
|
+
get insertedCount() {
|
|
81
|
+
return typeof this.result.nInserted !== 'number' ? 0 : this.result.nInserted;
|
|
82
|
+
}
|
|
83
|
+
/** Number of documents matched for update. */
|
|
84
|
+
get matchedCount() {
|
|
85
|
+
return typeof this.result.nMatched !== 'number' ? 0 : this.result.nMatched;
|
|
86
|
+
}
|
|
87
|
+
/** Number of documents modified. */
|
|
88
|
+
get modifiedCount() {
|
|
89
|
+
return typeof this.result.nModified !== 'number' ? 0 : this.result.nModified;
|
|
90
|
+
}
|
|
91
|
+
/** Number of documents deleted. */
|
|
92
|
+
get deletedCount() {
|
|
93
|
+
return typeof this.result.nRemoved !== 'number' ? 0 : this.result.nRemoved;
|
|
94
|
+
}
|
|
95
|
+
/** Number of documents upserted. */
|
|
96
|
+
get upsertedCount() {
|
|
97
|
+
return !this.result.upserted ? 0 : this.result.upserted.length;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Upserted document generated Id's, hash key is the index of the originating operation */
|
|
101
|
+
get upsertedIds() {
|
|
102
|
+
if (this[kUpsertedIds]) {
|
|
103
|
+
return this[kUpsertedIds];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this[kUpsertedIds] = {};
|
|
107
|
+
for (const doc of this.result.upserted || []) {
|
|
108
|
+
this[kUpsertedIds][doc.index] = doc._id;
|
|
109
|
+
}
|
|
110
|
+
return this[kUpsertedIds];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Inserted document generated Id's, hash key is the index of the originating operation */
|
|
114
|
+
get insertedIds() {
|
|
115
|
+
if (this[kInsertedIds]) {
|
|
116
|
+
return this[kInsertedIds];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
this[kInsertedIds] = {};
|
|
120
|
+
for (const doc of this.result.insertedIds || []) {
|
|
121
|
+
this[kInsertedIds][doc.index] = doc._id;
|
|
122
|
+
}
|
|
123
|
+
return this[kInsertedIds];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** The number of inserted documents @type {number} */
|
|
127
|
+
get n() {
|
|
128
|
+
return this.result.insertedCount;
|
|
71
129
|
}
|
|
72
130
|
|
|
73
131
|
/**
|
|
@@ -571,6 +629,35 @@ class BulkWriteError extends MongoError {
|
|
|
571
629
|
this.name = 'BulkWriteError';
|
|
572
630
|
this.result = result;
|
|
573
631
|
}
|
|
632
|
+
|
|
633
|
+
/** Number of documents inserted. */
|
|
634
|
+
get insertedCount() {
|
|
635
|
+
return this.result.insertedCount;
|
|
636
|
+
}
|
|
637
|
+
/** Number of documents matched for update. */
|
|
638
|
+
get matchedCount() {
|
|
639
|
+
return this.result.matchedCount;
|
|
640
|
+
}
|
|
641
|
+
/** Number of documents modified. */
|
|
642
|
+
get modifiedCount() {
|
|
643
|
+
return this.result.modifiedCount;
|
|
644
|
+
}
|
|
645
|
+
/** Number of documents deleted. */
|
|
646
|
+
get deletedCount() {
|
|
647
|
+
return this.result.deletedCount;
|
|
648
|
+
}
|
|
649
|
+
/** Number of documents upserted. */
|
|
650
|
+
get upsertedCount() {
|
|
651
|
+
return this.result.upsertedCount;
|
|
652
|
+
}
|
|
653
|
+
/** Inserted document generated Id's, hash key is the index of the originating operation */
|
|
654
|
+
get insertedIds() {
|
|
655
|
+
return this.result.insertedIds;
|
|
656
|
+
}
|
|
657
|
+
/** Upserted document generated Id's, hash key is the index of the originating operation */
|
|
658
|
+
get upsertedIds() {
|
|
659
|
+
return this.result.upsertedIds;
|
|
660
|
+
}
|
|
574
661
|
}
|
|
575
662
|
|
|
576
663
|
/**
|
|
@@ -737,15 +824,19 @@ class FindOperators {
|
|
|
737
824
|
|
|
738
825
|
/**
|
|
739
826
|
* backwards compatability for deleteOne
|
|
827
|
+
* @deprecated
|
|
740
828
|
*/
|
|
741
829
|
removeOne() {
|
|
830
|
+
emitWarningOnce('bulk operation `removeOne` has been deprecated, please use `deleteOne`');
|
|
742
831
|
return this.deleteOne();
|
|
743
832
|
}
|
|
744
833
|
|
|
745
834
|
/**
|
|
746
835
|
* backwards compatability for delete
|
|
836
|
+
* @deprecated
|
|
747
837
|
*/
|
|
748
838
|
remove() {
|
|
839
|
+
emitWarningOnce('bulk operation `remove` has been deprecated, please use `delete`');
|
|
749
840
|
return this.delete();
|
|
750
841
|
}
|
|
751
842
|
}
|
|
@@ -1041,6 +1132,9 @@ class BulkOperationBase {
|
|
|
1041
1132
|
}
|
|
1042
1133
|
|
|
1043
1134
|
if (op.insertMany) {
|
|
1135
|
+
emitWarningOnce(
|
|
1136
|
+
'bulk operation `insertMany` has been deprecated; use multiple `insertOne` ops instead'
|
|
1137
|
+
);
|
|
1044
1138
|
for (let i = 0; i < op.insertMany.length; i++) {
|
|
1045
1139
|
if (forceServerObjectId !== true && op.insertMany[i]._id == null)
|
|
1046
1140
|
op.insertMany[i]._id = new ObjectID();
|
|
@@ -1294,5 +1388,6 @@ module.exports = {
|
|
|
1294
1388
|
INSERT: INSERT,
|
|
1295
1389
|
UPDATE: UPDATE,
|
|
1296
1390
|
REMOVE: REMOVE,
|
|
1297
|
-
BulkWriteError
|
|
1391
|
+
BulkWriteError,
|
|
1392
|
+
BulkWriteResult
|
|
1298
1393
|
};
|
package/lib/cmap/connection.js
CHANGED
|
@@ -58,38 +58,9 @@ class Connection extends EventEmitter {
|
|
|
58
58
|
/* ignore errors, listen to `close` instead */
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
this.closed = true;
|
|
67
|
-
this[kQueue].forEach(op =>
|
|
68
|
-
op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} closed`))
|
|
69
|
-
);
|
|
70
|
-
this[kQueue].clear();
|
|
71
|
-
|
|
72
|
-
this.emit('close');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
stream.on('timeout', () => {
|
|
76
|
-
if (this.closed) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
stream.destroy();
|
|
81
|
-
this.closed = true;
|
|
82
|
-
this[kQueue].forEach(op =>
|
|
83
|
-
op.cb(
|
|
84
|
-
new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
|
|
85
|
-
beforeHandshake: this[kIsMaster] == null
|
|
86
|
-
})
|
|
87
|
-
)
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
this[kQueue].clear();
|
|
91
|
-
this.emit('close');
|
|
92
|
-
});
|
|
61
|
+
this[kMessageStream].on('error', error => this.handleIssue({ destroy: error }));
|
|
62
|
+
stream.on('close', () => this.handleIssue({ isClose: true }));
|
|
63
|
+
stream.on('timeout', () => this.handleIssue({ isTimeout: true, destroy: true }));
|
|
93
64
|
|
|
94
65
|
// hook the message stream up to the passed in stream
|
|
95
66
|
stream.pipe(this[kMessageStream]);
|
|
@@ -132,6 +103,39 @@ class Connection extends EventEmitter {
|
|
|
132
103
|
this[kLastUseTime] = now();
|
|
133
104
|
}
|
|
134
105
|
|
|
106
|
+
/**
|
|
107
|
+
* @param {{ isTimeout?: boolean; isClose?: boolean; destroy?: boolean | Error }} issue
|
|
108
|
+
*/
|
|
109
|
+
handleIssue(issue) {
|
|
110
|
+
if (this.closed) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (issue.destroy) {
|
|
115
|
+
this[kStream].destroy(typeof issue.destroy === 'boolean' ? undefined : issue.destroy);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.closed = true;
|
|
119
|
+
|
|
120
|
+
for (const idAndOp of this[kQueue]) {
|
|
121
|
+
const op = idAndOp[1];
|
|
122
|
+
if (issue.isTimeout) {
|
|
123
|
+
op.cb(
|
|
124
|
+
new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
|
|
125
|
+
beforeHandshake: this.ismaster == null
|
|
126
|
+
})
|
|
127
|
+
);
|
|
128
|
+
} else if (issue.isClose) {
|
|
129
|
+
op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} closed`));
|
|
130
|
+
} else {
|
|
131
|
+
op.cb(typeof issue.destroy === 'boolean' ? undefined : issue.destroy);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this[kQueue].clear();
|
|
136
|
+
this.emit('close');
|
|
137
|
+
}
|
|
138
|
+
|
|
135
139
|
destroy(options, callback) {
|
|
136
140
|
if (typeof options === 'function') {
|
|
137
141
|
callback = options;
|
|
@@ -313,6 +317,7 @@ function write(command, options, callback) {
|
|
|
313
317
|
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
|
|
314
318
|
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
|
|
315
319
|
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
|
|
320
|
+
bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false,
|
|
316
321
|
raw: typeof options.raw === 'boolean' ? options.raw : false
|
|
317
322
|
};
|
|
318
323
|
|
package/lib/collection.js
CHANGED
|
@@ -120,6 +120,8 @@ function Collection(db, topology, dbName, name, pkFactory, options) {
|
|
|
120
120
|
options == null || options.promoteBuffers == null
|
|
121
121
|
? db.s.options.promoteBuffers
|
|
122
122
|
: options.promoteBuffers;
|
|
123
|
+
const bsonRegExp =
|
|
124
|
+
options == null || options.bsonRegExp == null ? db.s.options.bsonRegExp : options.bsonRegExp;
|
|
123
125
|
const collectionHint = null;
|
|
124
126
|
|
|
125
127
|
const namespace = new MongoDBNamespace(dbName, name);
|
|
@@ -156,6 +158,8 @@ function Collection(db, topology, dbName, name, pkFactory, options) {
|
|
|
156
158
|
promoteValues: promoteValues,
|
|
157
159
|
// promoteBuffers
|
|
158
160
|
promoteBuffers: promoteBuffers,
|
|
161
|
+
// bsonRegExp
|
|
162
|
+
bsonRegExp: bsonRegExp,
|
|
159
163
|
// internalHint
|
|
160
164
|
internalHint: internalHint,
|
|
161
165
|
// collectionHint
|
|
@@ -303,6 +307,7 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'fields', 'snapshot', 'oplogReplay']
|
|
|
303
307
|
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
|
|
304
308
|
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
|
|
305
309
|
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
|
310
|
+
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
|
|
306
311
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
307
312
|
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
|
|
308
313
|
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
|
@@ -451,6 +456,8 @@ Collection.prototype.find = deprecateOptions(
|
|
|
451
456
|
newOptions.promoteValues = this.s.promoteValues;
|
|
452
457
|
if (newOptions.promoteBuffers == null && typeof this.s.promoteBuffers === 'boolean')
|
|
453
458
|
newOptions.promoteBuffers = this.s.promoteBuffers;
|
|
459
|
+
if (newOptions.bsonRegExp == null && typeof this.s.bsonRegExp === 'boolean')
|
|
460
|
+
newOptions.bsonRegExp = this.s.bsonRegExp;
|
|
454
461
|
|
|
455
462
|
// Sort options
|
|
456
463
|
if (findCommand.sort) {
|
|
@@ -1075,6 +1082,7 @@ Collection.prototype.save = deprecate(function(doc, options, callback) {
|
|
|
1075
1082
|
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
|
|
1076
1083
|
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
|
|
1077
1084
|
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
|
1085
|
+
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
|
|
1078
1086
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
1079
1087
|
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
|
|
1080
1088
|
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
|
@@ -1655,7 +1663,7 @@ Collection.prototype.stats = function(options, callback) {
|
|
|
1655
1663
|
|
|
1656
1664
|
/**
|
|
1657
1665
|
* @typedef {Object} Collection~findAndModifyWriteOpResult
|
|
1658
|
-
* @property {object} value Document returned from the `findAndModify` command. If no documents were found, `value` will be `null` by default
|
|
1666
|
+
* @property {object} value Document returned from the `findAndModify` command. If no documents were found, `value` will be `null` by default even if a document was upserted unless `returnDocument` is specified as `'after'`, in which case the upserted document will be returned.
|
|
1659
1667
|
* @property {object} lastErrorObject The raw lastErrorObject returned from the command. See {@link https://docs.mongodb.com/manual/reference/command/findAndModify/index.html#lasterrorobject|findAndModify command documentation}.
|
|
1660
1668
|
* @property {Number} ok Is 1 if the command executed correctly.
|
|
1661
1669
|
*/
|
|
@@ -1716,7 +1724,8 @@ Collection.prototype.findOneAndDelete = function(filter, options, callback) {
|
|
|
1716
1724
|
* @param {object} [options.projection] Limits the fields to return for all matching documents.
|
|
1717
1725
|
* @param {object} [options.sort] Determines which document the operation modifies if the query selects multiple documents.
|
|
1718
1726
|
* @param {boolean} [options.upsert=false] Upsert the document if it does not exist.
|
|
1719
|
-
* @param {
|
|
1727
|
+
* @param {'before'|'after'} [options.returnDocument='before'] When set to `'after'`, returns the updated document rather than the original. The default is `'before'`.
|
|
1728
|
+
* @param {boolean} [options.returnOriginal=true] **Deprecated** Use `options.returnDocument` instead.
|
|
1720
1729
|
* @param {boolean} [options.checkKeys=false] If true, will throw if bson documents start with `$` or include a `.` in any key value
|
|
1721
1730
|
* @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
|
|
1722
1731
|
* @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
|
@@ -1725,22 +1734,29 @@ Collection.prototype.findOneAndDelete = function(filter, options, callback) {
|
|
|
1725
1734
|
* @param {Collection~findAndModifyCallback} [callback] The collection result callback
|
|
1726
1735
|
* @return {Promise<Collection~findAndModifyWriteOpResultObject>} returns Promise if no callback passed
|
|
1727
1736
|
*/
|
|
1728
|
-
Collection.prototype.findOneAndReplace =
|
|
1729
|
-
|
|
1730
|
-
|
|
1737
|
+
Collection.prototype.findOneAndReplace = deprecateOptions(
|
|
1738
|
+
{
|
|
1739
|
+
name: 'collection.findOneAndReplace',
|
|
1740
|
+
deprecatedOptions: ['returnOriginal'],
|
|
1741
|
+
optionsIndex: 2
|
|
1742
|
+
},
|
|
1743
|
+
function(filter, replacement, options, callback) {
|
|
1744
|
+
if (typeof options === 'function') (callback = options), (options = {});
|
|
1745
|
+
options = options || {};
|
|
1731
1746
|
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1747
|
+
// Add ignoreUndefined
|
|
1748
|
+
if (this.s.options.ignoreUndefined) {
|
|
1749
|
+
options = Object.assign({}, options);
|
|
1750
|
+
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
|
1751
|
+
}
|
|
1737
1752
|
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
}
|
|
1753
|
+
return executeOperation(
|
|
1754
|
+
this.s.topology,
|
|
1755
|
+
new FindOneAndReplaceOperation(this, filter, replacement, options),
|
|
1756
|
+
callback
|
|
1757
|
+
);
|
|
1758
|
+
}
|
|
1759
|
+
);
|
|
1744
1760
|
|
|
1745
1761
|
/**
|
|
1746
1762
|
* Find a document and update it in one atomic operation. Requires a write lock for the duration of the operation.
|
|
@@ -1757,7 +1773,8 @@ Collection.prototype.findOneAndReplace = function(filter, replacement, options,
|
|
|
1757
1773
|
* @param {object} [options.projection] Limits the fields to return for all matching documents.
|
|
1758
1774
|
* @param {object} [options.sort] Determines which document the operation modifies if the query selects multiple documents.
|
|
1759
1775
|
* @param {boolean} [options.upsert=false] Upsert the document if it does not exist.
|
|
1760
|
-
* @param {
|
|
1776
|
+
* @param {'before'|'after'} [options.returnDocument='before'] When set to `'after'`, returns the updated document rather than the original. The default is `'before'`.
|
|
1777
|
+
* @param {boolean} [options.returnOriginal=true] **Deprecated** Use `options.returnDocument` instead.
|
|
1761
1778
|
* @param {boolean} [options.checkKeys=false] If true, will throw if bson documents start with `$` or include a `.` in any key value
|
|
1762
1779
|
* @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
|
|
1763
1780
|
* @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
|
@@ -1766,22 +1783,29 @@ Collection.prototype.findOneAndReplace = function(filter, replacement, options,
|
|
|
1766
1783
|
* @param {Collection~findAndModifyCallback} [callback] The collection result callback
|
|
1767
1784
|
* @return {Promise<Collection~findAndModifyWriteOpResultObject>} returns Promise if no callback passed
|
|
1768
1785
|
*/
|
|
1769
|
-
Collection.prototype.findOneAndUpdate =
|
|
1770
|
-
|
|
1771
|
-
|
|
1786
|
+
Collection.prototype.findOneAndUpdate = deprecateOptions(
|
|
1787
|
+
{
|
|
1788
|
+
name: 'collection.findOneAndUpdate',
|
|
1789
|
+
deprecatedOptions: ['returnOriginal'],
|
|
1790
|
+
optionsIndex: 2
|
|
1791
|
+
},
|
|
1792
|
+
function(filter, update, options, callback) {
|
|
1793
|
+
if (typeof options === 'function') (callback = options), (options = {});
|
|
1794
|
+
options = options || {};
|
|
1772
1795
|
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1796
|
+
// Add ignoreUndefined
|
|
1797
|
+
if (this.s.options.ignoreUndefined) {
|
|
1798
|
+
options = Object.assign({}, options);
|
|
1799
|
+
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
|
1800
|
+
}
|
|
1778
1801
|
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
}
|
|
1802
|
+
return executeOperation(
|
|
1803
|
+
this.s.topology,
|
|
1804
|
+
new FindOneAndUpdateOperation(this, filter, update, options),
|
|
1805
|
+
callback
|
|
1806
|
+
);
|
|
1807
|
+
}
|
|
1808
|
+
);
|
|
1785
1809
|
|
|
1786
1810
|
/**
|
|
1787
1811
|
* Find and update a document.
|
|
@@ -1883,6 +1907,7 @@ Collection.prototype.findAndRemove = deprecate(function(query, sort, options, ca
|
|
|
1883
1907
|
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
|
|
1884
1908
|
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
|
|
1885
1909
|
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
|
1910
|
+
* @param {boolean} [options.bsonRegExp=false] By default, regex returned from MDB will be native to the language. Setting to true will ensure that a BSON.BSONRegExp object is returned.
|
|
1886
1911
|
* @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
|
|
1887
1912
|
* @param {string} [options.comment] Add a comment to an aggregation command
|
|
1888
1913
|
* @param {string|object} [options.hint] Add an index selection hint to an aggregation command
|
|
@@ -2199,7 +2224,6 @@ Collection.prototype.initializeUnorderedBulkOp = function(options) {
|
|
|
2199
2224
|
* @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
|
|
2200
2225
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
|
2201
2226
|
* @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
|
2202
|
-
* @param {OrderedBulkOperation} callback The command result callback
|
|
2203
2227
|
* @return {null}
|
|
2204
2228
|
*/
|
|
2205
2229
|
Collection.prototype.initializeOrderedBulkOp = function(options) {
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const Msg = require('./core/connection/msg').Msg;
|
|
3
|
+
const KillCursor = require('./core/connection/commands').KillCursor;
|
|
4
|
+
const GetMore = require('./core/connection/commands').GetMore;
|
|
5
|
+
const deepCopy = require('./utils').deepCopy;
|
|
6
|
+
|
|
7
|
+
/** Commands that we want to redact because of the sensitive nature of their contents */
|
|
8
|
+
const SENSITIVE_COMMANDS = new Set([
|
|
9
|
+
'authenticate',
|
|
10
|
+
'saslStart',
|
|
11
|
+
'saslContinue',
|
|
12
|
+
'getnonce',
|
|
13
|
+
'createUser',
|
|
14
|
+
'updateUser',
|
|
15
|
+
'copydbgetnonce',
|
|
16
|
+
'copydbsaslstart',
|
|
17
|
+
'copydb'
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const HELLO_COMMANDS = new Set(['hello', 'ismaster', 'isMaster']);
|
|
21
|
+
|
|
22
|
+
const LEGACY_FIND_QUERY_MAP = {
|
|
23
|
+
$query: 'filter',
|
|
24
|
+
$orderby: 'sort',
|
|
25
|
+
$hint: 'hint',
|
|
26
|
+
$comment: 'comment',
|
|
27
|
+
$maxScan: 'maxScan',
|
|
28
|
+
$max: 'max',
|
|
29
|
+
$min: 'min',
|
|
30
|
+
$returnKey: 'returnKey',
|
|
31
|
+
$showDiskLoc: 'showRecordId',
|
|
32
|
+
$maxTimeMS: 'maxTimeMS',
|
|
33
|
+
$snapshot: 'snapshot'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const LEGACY_FIND_OPTIONS_MAP = {
|
|
37
|
+
numberToSkip: 'skip',
|
|
38
|
+
numberToReturn: 'batchSize',
|
|
39
|
+
returnFieldsSelector: 'projection'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const OP_QUERY_KEYS = [
|
|
43
|
+
'tailable',
|
|
44
|
+
'oplogReplay',
|
|
45
|
+
'noCursorTimeout',
|
|
46
|
+
'awaitData',
|
|
47
|
+
'partial',
|
|
48
|
+
'exhaust'
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const collectionName = command => command.ns.split('.')[1];
|
|
52
|
+
|
|
53
|
+
const shouldRedactCommand = (commandName, cmd) =>
|
|
54
|
+
SENSITIVE_COMMANDS.has(commandName) ||
|
|
55
|
+
(HELLO_COMMANDS.has(commandName) && !!cmd.speculativeAuthenticate);
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Extract the actual command from the query, possibly upconverting if it's a legacy
|
|
59
|
+
* format
|
|
60
|
+
*
|
|
61
|
+
* @param {Object} command the command
|
|
62
|
+
*/
|
|
63
|
+
const extractCommand = command => {
|
|
64
|
+
let extractedCommand;
|
|
65
|
+
if (command instanceof GetMore) {
|
|
66
|
+
extractedCommand = {
|
|
67
|
+
getMore: deepCopy(command.cursorId),
|
|
68
|
+
collection: collectionName(command),
|
|
69
|
+
batchSize: command.numberToReturn
|
|
70
|
+
};
|
|
71
|
+
} else if (command instanceof KillCursor) {
|
|
72
|
+
extractedCommand = {
|
|
73
|
+
killCursors: collectionName(command),
|
|
74
|
+
cursors: deepCopy(command.cursorIds)
|
|
75
|
+
};
|
|
76
|
+
} else if (command instanceof Msg) {
|
|
77
|
+
extractedCommand = deepCopy(command.command);
|
|
78
|
+
} else if (command.query && command.query.$query) {
|
|
79
|
+
let result;
|
|
80
|
+
if (command.ns === 'admin.$cmd') {
|
|
81
|
+
// upconvert legacy command
|
|
82
|
+
result = Object.assign({}, command.query.$query);
|
|
83
|
+
} else {
|
|
84
|
+
// upconvert legacy find command
|
|
85
|
+
result = { find: collectionName(command) };
|
|
86
|
+
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
|
|
87
|
+
if (typeof command.query[key] !== 'undefined')
|
|
88
|
+
result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
|
|
93
|
+
if (typeof command[key] !== 'undefined')
|
|
94
|
+
result[LEGACY_FIND_OPTIONS_MAP[key]] = deepCopy(command[key]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
OP_QUERY_KEYS.forEach(key => {
|
|
98
|
+
if (command[key]) result[key] = command[key];
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (typeof command.pre32Limit !== 'undefined') {
|
|
102
|
+
result.limit = command.pre32Limit;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (command.query.$explain) {
|
|
106
|
+
extractedCommand = { explain: result };
|
|
107
|
+
} else {
|
|
108
|
+
extractedCommand = result;
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
extractedCommand = deepCopy(command.query || command);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const commandName = Object.keys(extractedCommand)[0];
|
|
115
|
+
return {
|
|
116
|
+
cmd: extractedCommand,
|
|
117
|
+
name: commandName,
|
|
118
|
+
shouldRedact: shouldRedactCommand(commandName, extractedCommand)
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
module.exports = {
|
|
123
|
+
extractCommand
|
|
124
|
+
};
|
|
@@ -49,16 +49,16 @@ class MongoCredentials {
|
|
|
49
49
|
this.mechanism = options.mechanism || 'default';
|
|
50
50
|
this.mechanismProperties = options.mechanismProperties || {};
|
|
51
51
|
|
|
52
|
-
if (
|
|
53
|
-
if (this.username
|
|
52
|
+
if (/MONGODB-AWS/i.test(this.mechanism)) {
|
|
53
|
+
if (!this.username && process.env.AWS_ACCESS_KEY_ID) {
|
|
54
54
|
this.username = process.env.AWS_ACCESS_KEY_ID;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (this.password
|
|
57
|
+
if (!this.password && process.env.AWS_SECRET_ACCESS_KEY) {
|
|
58
58
|
this.password = process.env.AWS_SECRET_ACCESS_KEY;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
if (this.mechanismProperties.AWS_SESSION_TOKEN
|
|
61
|
+
if (!this.mechanismProperties.AWS_SESSION_TOKEN && process.env.AWS_SESSION_TOKEN) {
|
|
62
62
|
this.mechanismProperties.AWS_SESSION_TOKEN = process.env.AWS_SESSION_TOKEN;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -90,7 +90,7 @@ class MongoCredentials {
|
|
|
90
90
|
*/
|
|
91
91
|
resolveAuthMechanism(ismaster) {
|
|
92
92
|
// If the mechanism is not "default", then it does not need to be resolved
|
|
93
|
-
if (
|
|
93
|
+
if (/DEFAULT/i.test(this.mechanism)) {
|
|
94
94
|
return new MongoCredentials({
|
|
95
95
|
username: this.username,
|
|
96
96
|
password: this.password,
|