mongodb 3.5.9 → 3.6.0
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 +110 -18
- package/lib/admin.js +1 -0
- package/lib/bulk/common.js +48 -4
- package/lib/change_stream.js +7 -3
- package/lib/cmap/connection.js +9 -6
- package/lib/collection.js +61 -84
- package/lib/core/auth/auth_provider.js +29 -132
- package/lib/core/auth/defaultAuthProviders.js +2 -2
- package/lib/core/auth/gssapi.js +69 -219
- package/lib/core/auth/mongo_credentials.js +29 -3
- package/lib/core/auth/mongocr.js +6 -12
- package/lib/core/auth/mongodb_aws.js +256 -0
- package/lib/core/auth/plain.js +5 -12
- package/lib/core/auth/scram.js +229 -212
- package/lib/core/auth/x509.js +25 -16
- package/lib/core/connection/connect.js +97 -161
- package/lib/core/connection/connection.js +71 -3
- package/lib/core/connection/pool.js +2 -2
- package/lib/core/cursor.js +30 -39
- package/lib/core/error.js +82 -8
- package/lib/core/sdam/common.js +8 -0
- package/lib/core/sdam/monitor.js +240 -79
- package/lib/core/sdam/server.js +82 -17
- package/lib/core/sdam/server_description.js +47 -2
- package/lib/core/sdam/topology.js +43 -32
- package/lib/core/sdam/topology_description.js +21 -3
- package/lib/core/sessions.js +14 -16
- package/lib/core/topologies/mongos.js +18 -6
- package/lib/core/topologies/read_preference.js +71 -7
- package/lib/core/topologies/replset.js +4 -4
- package/lib/core/topologies/server.js +1 -1
- package/lib/core/topologies/shared.js +39 -16
- package/lib/core/uri_parser.js +41 -6
- package/lib/core/utils.js +30 -0
- package/lib/core/wireprotocol/command.js +2 -10
- package/lib/core/wireprotocol/constants.js +2 -2
- package/lib/core/wireprotocol/query.js +4 -0
- package/lib/cursor.js +0 -1
- package/lib/db.js +7 -6
- package/lib/error.js +6 -1
- package/lib/gridfs-stream/download.js +13 -2
- package/lib/mongo_client.js +6 -4
- package/lib/operations/collection_ops.js +1 -22
- package/lib/operations/command.js +2 -3
- package/lib/operations/command_v2.js +8 -7
- package/lib/operations/common_functions.js +3 -0
- package/lib/operations/connect.js +11 -14
- package/lib/operations/create_collection.js +37 -52
- package/lib/operations/create_indexes.js +91 -35
- package/lib/operations/db_ops.js +1 -2
- package/lib/operations/find.js +9 -3
- package/lib/operations/find_and_modify.js +17 -0
- package/lib/operations/find_one_and_delete.js +5 -0
- package/lib/operations/find_one_and_replace.js +13 -0
- package/lib/operations/find_one_and_update.js +13 -0
- package/lib/operations/geo_haystack_search.js +2 -2
- package/lib/operations/map_reduce.js +3 -3
- package/lib/operations/operation.js +2 -1
- package/lib/operations/re_index.js +22 -17
- package/lib/operations/replace_one.js +11 -4
- package/lib/operations/run_command.js +19 -0
- package/lib/operations/update_many.js +5 -0
- package/lib/operations/update_one.js +5 -0
- package/lib/operations/validate_collection.js +1 -2
- package/lib/topologies/mongos.js +1 -1
- package/lib/topologies/replset.js +1 -1
- package/lib/topologies/server.js +1 -1
- package/lib/topologies/topology_base.js +4 -4
- package/lib/utils.js +18 -60
- package/lib/write_concern.js +10 -0
- package/package.json +2 -2
- package/lib/core/auth/sspi.js +0 -131
- package/lib/operations/create_index.js +0 -92
package/lib/topologies/mongos.js
CHANGED
|
@@ -82,7 +82,7 @@ var legalOptionNames = [
|
|
|
82
82
|
* @param {object} [options.socketOptions] Socket options
|
|
83
83
|
* @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
|
|
84
84
|
* @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
|
|
85
|
-
* @param {number} [options.socketOptions.keepAliveInitialDelay=
|
|
85
|
+
* @param {number} [options.socketOptions.keepAliveInitialDelay=120000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
|
|
86
86
|
* @param {number} [options.socketOptions.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
|
|
87
87
|
* @param {number} [options.socketOptions.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
|
|
88
88
|
* @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
|
|
@@ -92,7 +92,7 @@ var legalOptionNames = [
|
|
|
92
92
|
* @param {object} [options.socketOptions] Socket options
|
|
93
93
|
* @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
|
|
94
94
|
* @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
|
|
95
|
-
* @param {number} [options.socketOptions.keepAliveInitialDelay=
|
|
95
|
+
* @param {number} [options.socketOptions.keepAliveInitialDelay=120000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
|
|
96
96
|
* @param {number} [options.socketOptions.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
|
|
97
97
|
* @param {number} [options.socketOptions.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
|
|
98
98
|
* @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
|
package/lib/topologies/server.js
CHANGED
|
@@ -84,7 +84,7 @@ var legalOptionNames = [
|
|
|
84
84
|
* @param {boolean} [options.socketOptions.autoReconnect=true] Reconnect on error.
|
|
85
85
|
* @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
|
|
86
86
|
* @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
|
|
87
|
-
* @param {number} [options.socketOptions.keepAliveInitialDelay=
|
|
87
|
+
* @param {number} [options.socketOptions.keepAliveInitialDelay=120000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
|
|
88
88
|
* @param {number} [options.socketOptions.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
|
|
89
89
|
* @param {number} [options.socketOptions.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
|
|
90
90
|
* @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const EventEmitter = require('events'),
|
|
4
4
|
MongoError = require('../core').MongoError,
|
|
5
5
|
f = require('util').format,
|
|
6
|
-
|
|
6
|
+
ReadPreference = require('../core').ReadPreference,
|
|
7
7
|
ClientSession = require('../core').Sessions.ClientSession;
|
|
8
8
|
|
|
9
9
|
// The store of ops
|
|
@@ -293,7 +293,7 @@ class TopologyBase extends EventEmitter {
|
|
|
293
293
|
|
|
294
294
|
// Command
|
|
295
295
|
command(ns, cmd, options, callback) {
|
|
296
|
-
this.s.coreTopology.command(ns.toString(), cmd,
|
|
296
|
+
this.s.coreTopology.command(ns.toString(), cmd, ReadPreference.translate(options), callback);
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
// Insert
|
|
@@ -314,7 +314,7 @@ class TopologyBase extends EventEmitter {
|
|
|
314
314
|
// IsConnected
|
|
315
315
|
isConnected(options) {
|
|
316
316
|
options = options || {};
|
|
317
|
-
options =
|
|
317
|
+
options = ReadPreference.translate(options);
|
|
318
318
|
|
|
319
319
|
return this.s.coreTopology.isConnected(options);
|
|
320
320
|
}
|
|
@@ -327,7 +327,7 @@ class TopologyBase extends EventEmitter {
|
|
|
327
327
|
// Cursor
|
|
328
328
|
cursor(ns, cmd, options) {
|
|
329
329
|
options = options || {};
|
|
330
|
-
options =
|
|
330
|
+
options = ReadPreference.translate(options);
|
|
331
331
|
options.disconnectHandler = this.s.store;
|
|
332
332
|
options.topology = this;
|
|
333
333
|
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const MongoError = require('./core/error').MongoError;
|
|
3
|
-
const ReadPreference = require('./core/topologies/read_preference');
|
|
4
3
|
const WriteConcern = require('./write_concern');
|
|
5
4
|
|
|
6
5
|
var shallowClone = function(obj) {
|
|
@@ -9,31 +8,6 @@ var shallowClone = function(obj) {
|
|
|
9
8
|
return copy;
|
|
10
9
|
};
|
|
11
10
|
|
|
12
|
-
// Figure out the read preference
|
|
13
|
-
var translateReadPreference = function(options) {
|
|
14
|
-
var r = null;
|
|
15
|
-
if (options.readPreference) {
|
|
16
|
-
r = options.readPreference;
|
|
17
|
-
} else {
|
|
18
|
-
return options;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (typeof r === 'string') {
|
|
22
|
-
options.readPreference = new ReadPreference(r);
|
|
23
|
-
} else if (r && !(r instanceof ReadPreference) && typeof r === 'object') {
|
|
24
|
-
const mode = r.mode || r.preference;
|
|
25
|
-
if (mode && typeof mode === 'string') {
|
|
26
|
-
options.readPreference = new ReadPreference(mode, r.tags, {
|
|
27
|
-
maxStalenessSeconds: r.maxStalenessSeconds
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
} else if (!(r instanceof ReadPreference)) {
|
|
31
|
-
throw new TypeError('Invalid read preference: ' + r);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return options;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
11
|
// Set simple property
|
|
38
12
|
var getSingleProperty = function(obj, name, value) {
|
|
39
13
|
Object.defineProperty(obj, name, {
|
|
@@ -490,37 +464,6 @@ function applyWriteConcern(target, sources, options) {
|
|
|
490
464
|
return target;
|
|
491
465
|
}
|
|
492
466
|
|
|
493
|
-
/**
|
|
494
|
-
* Resolves a read preference based on well-defined inheritance rules. This method will not only
|
|
495
|
-
* determine the read preference (if there is one), but will also ensure the returned value is a
|
|
496
|
-
* properly constructed instance of `ReadPreference`.
|
|
497
|
-
*
|
|
498
|
-
* @param {Collection|Db|MongoClient} parent The parent of the operation on which to determine the read
|
|
499
|
-
* preference, used for determining the inherited read preference.
|
|
500
|
-
* @param {Object} options The options passed into the method, potentially containing a read preference
|
|
501
|
-
* @returns {(ReadPreference|null)} The resolved read preference
|
|
502
|
-
*/
|
|
503
|
-
function resolveReadPreference(parent, options) {
|
|
504
|
-
options = options || {};
|
|
505
|
-
const session = options.session;
|
|
506
|
-
|
|
507
|
-
const inheritedReadPreference = parent.readPreference;
|
|
508
|
-
|
|
509
|
-
let readPreference;
|
|
510
|
-
if (options.readPreference) {
|
|
511
|
-
readPreference = ReadPreference.fromOptions(options);
|
|
512
|
-
} else if (session && session.inTransaction() && session.transaction.options.readPreference) {
|
|
513
|
-
// The transaction’s read preference MUST override all other user configurable read preferences.
|
|
514
|
-
readPreference = session.transaction.options.readPreference;
|
|
515
|
-
} else if (inheritedReadPreference != null) {
|
|
516
|
-
readPreference = inheritedReadPreference;
|
|
517
|
-
} else {
|
|
518
|
-
throw new Error('No readPreference was provided or inherited.');
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
return typeof readPreference === 'string' ? new ReadPreference(readPreference) : readPreference;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
467
|
/**
|
|
525
468
|
* Checks if a given value is a Promise
|
|
526
469
|
*
|
|
@@ -778,6 +721,12 @@ function makeInterruptableAsyncInterval(fn, options) {
|
|
|
778
721
|
const timeUntilNextCall = Math.max(interval - timeSinceLastCall, 0);
|
|
779
722
|
lastWakeTime = currentTime;
|
|
780
723
|
|
|
724
|
+
// For the streaming protocol: there is nothing obviously stopping this
|
|
725
|
+
// interval from being woken up again while we are waiting "infinitely"
|
|
726
|
+
// for `fn` to be called again`. Since the function effectively
|
|
727
|
+
// never completes, the `timeUntilNextCall` will continue to grow
|
|
728
|
+
// negatively unbounded, so it will never trigger a reschedule here.
|
|
729
|
+
|
|
781
730
|
// debounce multiple calls to wake within the `minInterval`
|
|
782
731
|
if (timeSinceLastWake < minInterval) {
|
|
783
732
|
return;
|
|
@@ -810,6 +759,7 @@ function makeInterruptableAsyncInterval(fn, options) {
|
|
|
810
759
|
function executeAndReschedule() {
|
|
811
760
|
lastWakeTime = 0;
|
|
812
761
|
lastCallTime = now();
|
|
762
|
+
|
|
813
763
|
fn(err => {
|
|
814
764
|
if (err) throw err;
|
|
815
765
|
reschedule(interval);
|
|
@@ -826,6 +776,15 @@ function makeInterruptableAsyncInterval(fn, options) {
|
|
|
826
776
|
return { wake, stop };
|
|
827
777
|
}
|
|
828
778
|
|
|
779
|
+
function hasAtomicOperators(doc) {
|
|
780
|
+
if (Array.isArray(doc)) {
|
|
781
|
+
return doc.reduce((err, u) => err || hasAtomicOperators(u), null);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
const keys = Object.keys(doc);
|
|
785
|
+
return keys.length > 0 && keys[0][0] === '$';
|
|
786
|
+
}
|
|
787
|
+
|
|
829
788
|
module.exports = {
|
|
830
789
|
filterOptions,
|
|
831
790
|
mergeOptions,
|
|
@@ -843,7 +802,6 @@ module.exports = {
|
|
|
843
802
|
debugOptions,
|
|
844
803
|
MAX_JS_INT: Number.MAX_SAFE_INTEGER + 1,
|
|
845
804
|
mergeOptionsAndWriteConcern,
|
|
846
|
-
translateReadPreference,
|
|
847
805
|
executeLegacyOperation,
|
|
848
806
|
applyRetryableWrites,
|
|
849
807
|
applyWriteConcern,
|
|
@@ -853,11 +811,11 @@ module.exports = {
|
|
|
853
811
|
deprecateOptions,
|
|
854
812
|
SUPPORTS,
|
|
855
813
|
MongoDBNamespace,
|
|
856
|
-
resolveReadPreference,
|
|
857
814
|
emitDeprecationWarning,
|
|
858
815
|
makeCounter,
|
|
859
816
|
maybePromise,
|
|
860
817
|
now,
|
|
861
818
|
calculateDurationInMs,
|
|
862
|
-
makeInterruptableAsyncInterval
|
|
819
|
+
makeInterruptableAsyncInterval,
|
|
820
|
+
hasAtomicOperators
|
|
863
821
|
};
|
package/lib/write_concern.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const kWriteConcernKeys = new Set(['w', 'wtimeout', 'j', 'fsync']);
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* The **WriteConcern** class is a class that represents a MongoDB WriteConcern.
|
|
5
7
|
* @class
|
|
@@ -51,6 +53,14 @@ class WriteConcern {
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
if (options.writeConcern) {
|
|
56
|
+
if (typeof options.writeConcern === 'string') {
|
|
57
|
+
return new WriteConcern(options.writeConcern);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!Object.keys(options.writeConcern).some(key => kWriteConcernKeys.has(key))) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
54
64
|
return new WriteConcern(
|
|
55
65
|
options.writeConcern.w,
|
|
56
66
|
options.writeConcern.wtimeout,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongodb",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "The official MongoDB driver for Node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"url": "https://github.com/mongodb/node-mongodb-native/issues"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
|
-
"atlas": "
|
|
67
|
+
"atlas": "mocha --opts '{}' ./test/manual/atlas_connectivity.test.js",
|
|
68
68
|
"test": "npm run lint && mocha --recursive test/functional test/unit test/core",
|
|
69
69
|
"test-nolint": "mocha --recursive test/functional test/unit test/core",
|
|
70
70
|
"coverage": "istanbul cover mongodb-test-runner -- -t 60000 test/core test/unit test/functional",
|
package/lib/core/auth/sspi.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const AuthProvider = require('./auth_provider').AuthProvider;
|
|
4
|
-
const retrieveKerberos = require('../utils').retrieveKerberos;
|
|
5
|
-
let kerberos;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Creates a new SSPI authentication mechanism
|
|
9
|
-
* @class
|
|
10
|
-
* @extends AuthProvider
|
|
11
|
-
*/
|
|
12
|
-
class SSPI extends AuthProvider {
|
|
13
|
-
/**
|
|
14
|
-
* Implementation of authentication for a single connection
|
|
15
|
-
* @override
|
|
16
|
-
*/
|
|
17
|
-
_authenticateSingleConnection(sendAuthCommand, connection, credentials, callback) {
|
|
18
|
-
// TODO: Destructure this
|
|
19
|
-
const username = credentials.username;
|
|
20
|
-
const password = credentials.password;
|
|
21
|
-
const mechanismProperties = credentials.mechanismProperties;
|
|
22
|
-
const gssapiServiceName =
|
|
23
|
-
mechanismProperties['gssapiservicename'] ||
|
|
24
|
-
mechanismProperties['gssapiServiceName'] ||
|
|
25
|
-
'mongodb';
|
|
26
|
-
|
|
27
|
-
SSIPAuthenticate(
|
|
28
|
-
this,
|
|
29
|
-
kerberos.processes.MongoAuthProcess,
|
|
30
|
-
username,
|
|
31
|
-
password,
|
|
32
|
-
gssapiServiceName,
|
|
33
|
-
sendAuthCommand,
|
|
34
|
-
connection,
|
|
35
|
-
mechanismProperties,
|
|
36
|
-
callback
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Authenticate
|
|
42
|
-
* @override
|
|
43
|
-
* @method
|
|
44
|
-
*/
|
|
45
|
-
auth(sendAuthCommand, connections, credentials, callback) {
|
|
46
|
-
if (kerberos == null) {
|
|
47
|
-
try {
|
|
48
|
-
kerberos = retrieveKerberos();
|
|
49
|
-
} catch (e) {
|
|
50
|
-
return callback(e, null);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
super.auth(sendAuthCommand, connections, credentials, callback);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function SSIPAuthenticate(
|
|
59
|
-
self,
|
|
60
|
-
MongoAuthProcess,
|
|
61
|
-
username,
|
|
62
|
-
password,
|
|
63
|
-
gssapiServiceName,
|
|
64
|
-
sendAuthCommand,
|
|
65
|
-
connection,
|
|
66
|
-
options,
|
|
67
|
-
callback
|
|
68
|
-
) {
|
|
69
|
-
const authProcess = new MongoAuthProcess(
|
|
70
|
-
connection.host,
|
|
71
|
-
connection.port,
|
|
72
|
-
gssapiServiceName,
|
|
73
|
-
options
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
function authCommand(command, authCb) {
|
|
77
|
-
sendAuthCommand(connection, '$external.$cmd', command, authCb);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
authProcess.init(username, password, err => {
|
|
81
|
-
if (err) return callback(err, false);
|
|
82
|
-
|
|
83
|
-
authProcess.transition('', (err, payload) => {
|
|
84
|
-
if (err) return callback(err, false);
|
|
85
|
-
|
|
86
|
-
const command = {
|
|
87
|
-
saslStart: 1,
|
|
88
|
-
mechanism: 'GSSAPI',
|
|
89
|
-
payload,
|
|
90
|
-
autoAuthorize: 1
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
authCommand(command, (err, doc) => {
|
|
94
|
-
if (err) return callback(err, false);
|
|
95
|
-
|
|
96
|
-
authProcess.transition(doc.payload, (err, payload) => {
|
|
97
|
-
if (err) return callback(err, false);
|
|
98
|
-
const command = {
|
|
99
|
-
saslContinue: 1,
|
|
100
|
-
conversationId: doc.conversationId,
|
|
101
|
-
payload
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
authCommand(command, (err, doc) => {
|
|
105
|
-
if (err) return callback(err, false);
|
|
106
|
-
|
|
107
|
-
authProcess.transition(doc.payload, (err, payload) => {
|
|
108
|
-
if (err) return callback(err, false);
|
|
109
|
-
const command = {
|
|
110
|
-
saslContinue: 1,
|
|
111
|
-
conversationId: doc.conversationId,
|
|
112
|
-
payload
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
authCommand(command, (err, response) => {
|
|
116
|
-
if (err) return callback(err, false);
|
|
117
|
-
|
|
118
|
-
authProcess.transition(null, err => {
|
|
119
|
-
if (err) return callback(err, null);
|
|
120
|
-
callback(null, response);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
module.exports = SSPI;
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Aspect = require('./operation').Aspect;
|
|
4
|
-
const CommandOperation = require('./command');
|
|
5
|
-
const defineAspects = require('./operation').defineAspects;
|
|
6
|
-
const handleCallback = require('../utils').handleCallback;
|
|
7
|
-
const MongoError = require('../core').MongoError;
|
|
8
|
-
const parseIndexOptions = require('../utils').parseIndexOptions;
|
|
9
|
-
|
|
10
|
-
const keysToOmit = new Set([
|
|
11
|
-
'name',
|
|
12
|
-
'key',
|
|
13
|
-
'writeConcern',
|
|
14
|
-
'w',
|
|
15
|
-
'wtimeout',
|
|
16
|
-
'j',
|
|
17
|
-
'fsync',
|
|
18
|
-
'readPreference',
|
|
19
|
-
'session'
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
class CreateIndexOperation extends CommandOperation {
|
|
23
|
-
constructor(db, name, fieldOrSpec, options) {
|
|
24
|
-
super(db, options);
|
|
25
|
-
|
|
26
|
-
// Build the index
|
|
27
|
-
const indexParameters = parseIndexOptions(fieldOrSpec);
|
|
28
|
-
// Generate the index name
|
|
29
|
-
const indexName = typeof options.name === 'string' ? options.name : indexParameters.name;
|
|
30
|
-
// Set up the index
|
|
31
|
-
const indexesObject = { name: indexName, key: indexParameters.fieldHash };
|
|
32
|
-
|
|
33
|
-
this.name = name;
|
|
34
|
-
this.fieldOrSpec = fieldOrSpec;
|
|
35
|
-
this.indexes = indexesObject;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
_buildCommand() {
|
|
39
|
-
const options = this.options;
|
|
40
|
-
const name = this.name;
|
|
41
|
-
const indexes = this.indexes;
|
|
42
|
-
|
|
43
|
-
// merge all the options
|
|
44
|
-
for (let optionName in options) {
|
|
45
|
-
if (!keysToOmit.has(optionName)) {
|
|
46
|
-
indexes[optionName] = options[optionName];
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Create command, apply write concern to command
|
|
51
|
-
const cmd = { createIndexes: name, indexes: [indexes] };
|
|
52
|
-
|
|
53
|
-
return cmd;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
execute(callback) {
|
|
57
|
-
const db = this.db;
|
|
58
|
-
const options = this.options;
|
|
59
|
-
const indexes = this.indexes;
|
|
60
|
-
|
|
61
|
-
// Get capabilities
|
|
62
|
-
const capabilities = db.s.topology.capabilities();
|
|
63
|
-
|
|
64
|
-
// Did the user pass in a collation, check if our write server supports it
|
|
65
|
-
if (options.collation && capabilities && !capabilities.commandsTakeCollation) {
|
|
66
|
-
// Create a new error
|
|
67
|
-
const error = new MongoError('server/primary/mongos does not support collation');
|
|
68
|
-
error.code = 67;
|
|
69
|
-
// Return the error
|
|
70
|
-
return callback(error);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Ensure we have a callback
|
|
74
|
-
if (options.writeConcern && typeof callback !== 'function') {
|
|
75
|
-
throw MongoError.create({
|
|
76
|
-
message: 'Cannot use a writeConcern without a provided callback',
|
|
77
|
-
driver: true
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Attempt to run using createIndexes command
|
|
82
|
-
super.execute((err, result) => {
|
|
83
|
-
if (err == null) return handleCallback(callback, err, indexes.name);
|
|
84
|
-
|
|
85
|
-
return handleCallback(callback, err, result);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
defineAspects(CreateIndexOperation, Aspect.WRITE_OPERATION);
|
|
91
|
-
|
|
92
|
-
module.exports = CreateIndexOperation;
|