mongodb 3.2.5 → 3.3.0-beta2
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 +0 -10
- package/index.js +4 -4
- package/lib/admin.js +56 -56
- package/lib/aggregation_cursor.js +7 -3
- package/lib/bulk/common.js +18 -13
- package/lib/change_stream.js +196 -89
- package/lib/collection.js +217 -169
- package/lib/command_cursor.js +17 -7
- package/lib/core/auth/auth_provider.js +158 -0
- package/lib/core/auth/defaultAuthProviders.js +29 -0
- package/lib/core/auth/gssapi.js +241 -0
- package/lib/core/auth/mongo_credentials.js +81 -0
- package/lib/core/auth/mongocr.js +51 -0
- package/lib/core/auth/plain.js +35 -0
- package/lib/core/auth/scram.js +293 -0
- package/lib/core/auth/sspi.js +131 -0
- package/lib/core/auth/x509.js +26 -0
- package/lib/core/connection/apm.js +236 -0
- package/lib/core/connection/command_result.js +36 -0
- package/lib/core/connection/commands.js +507 -0
- package/lib/core/connection/connect.js +370 -0
- package/lib/core/connection/connection.js +624 -0
- package/lib/core/connection/logger.js +246 -0
- package/lib/core/connection/msg.js +219 -0
- package/lib/core/connection/pool.js +1285 -0
- package/lib/core/connection/utils.js +57 -0
- package/lib/core/cursor.js +752 -0
- package/lib/core/error.js +186 -0
- package/lib/core/index.js +50 -0
- package/lib/core/sdam/monitoring.js +228 -0
- package/lib/core/sdam/server.js +467 -0
- package/lib/core/sdam/server_description.js +163 -0
- package/lib/core/sdam/server_selectors.js +244 -0
- package/lib/core/sdam/srv_polling.js +135 -0
- package/lib/core/sdam/topology.js +1151 -0
- package/lib/core/sdam/topology_description.js +408 -0
- package/lib/core/sessions.js +711 -0
- package/lib/core/tools/smoke_plugin.js +61 -0
- package/lib/core/topologies/mongos.js +1337 -0
- package/lib/core/topologies/read_preference.js +202 -0
- package/lib/core/topologies/replset.js +1507 -0
- package/lib/core/topologies/replset_state.js +1121 -0
- package/lib/core/topologies/server.js +984 -0
- package/lib/core/topologies/shared.js +453 -0
- package/lib/core/transactions.js +167 -0
- package/lib/core/uri_parser.js +631 -0
- package/lib/core/utils.js +165 -0
- package/lib/core/wireprotocol/command.js +170 -0
- package/lib/core/wireprotocol/compression.js +73 -0
- package/lib/core/wireprotocol/constants.js +13 -0
- package/lib/core/wireprotocol/get_more.js +86 -0
- package/lib/core/wireprotocol/index.js +18 -0
- package/lib/core/wireprotocol/kill_cursors.js +70 -0
- package/lib/core/wireprotocol/query.js +224 -0
- package/lib/core/wireprotocol/shared.js +115 -0
- package/lib/core/wireprotocol/write_command.js +50 -0
- package/lib/cursor.js +40 -46
- package/lib/db.js +141 -95
- package/lib/dynamic_loaders.js +32 -0
- package/lib/error.js +12 -10
- package/lib/gridfs/chunk.js +2 -2
- package/lib/gridfs/grid_store.js +31 -25
- package/lib/gridfs-stream/index.js +4 -4
- package/lib/gridfs-stream/upload.js +1 -1
- package/lib/mongo_client.js +37 -15
- package/lib/operations/add_user.js +96 -0
- package/lib/operations/aggregate.js +24 -13
- package/lib/operations/aggregate_operation.js +127 -0
- package/lib/operations/bulk_write.js +104 -0
- package/lib/operations/close.js +47 -0
- package/lib/operations/collection_ops.js +28 -287
- package/lib/operations/collections.js +55 -0
- package/lib/operations/command.js +120 -0
- package/lib/operations/command_v2.js +43 -0
- package/lib/operations/common_functions.js +372 -0
- package/lib/operations/{mongo_client_ops.js → connect.js} +185 -157
- package/lib/operations/count.js +72 -0
- package/lib/operations/count_documents.js +46 -0
- package/lib/operations/create_collection.js +118 -0
- package/lib/operations/create_index.js +92 -0
- package/lib/operations/create_indexes.js +61 -0
- package/lib/operations/cursor_ops.js +3 -4
- package/lib/operations/db_ops.js +15 -12
- package/lib/operations/delete_many.js +25 -0
- package/lib/operations/delete_one.js +25 -0
- package/lib/operations/distinct.js +85 -0
- package/lib/operations/drop.js +53 -0
- package/lib/operations/drop_index.js +42 -0
- package/lib/operations/drop_indexes.js +23 -0
- package/lib/operations/estimated_document_count.js +33 -0
- package/lib/operations/execute_db_admin_command.js +34 -0
- package/lib/operations/execute_operation.js +165 -0
- package/lib/operations/explain.js +23 -0
- package/lib/operations/find_and_modify.js +98 -0
- package/lib/operations/find_one.js +33 -0
- package/lib/operations/find_one_and_delete.js +16 -0
- package/lib/operations/find_one_and_replace.js +18 -0
- package/lib/operations/find_one_and_update.js +19 -0
- package/lib/operations/geo_haystack_search.js +79 -0
- package/lib/operations/has_next.js +40 -0
- package/lib/operations/index_exists.js +39 -0
- package/lib/operations/index_information.js +23 -0
- package/lib/operations/indexes.js +22 -0
- package/lib/operations/insert_many.js +63 -0
- package/lib/operations/insert_one.js +75 -0
- package/lib/operations/is_capped.js +19 -0
- package/lib/operations/list_indexes.js +66 -0
- package/lib/operations/map_reduce.js +189 -0
- package/lib/operations/next.js +32 -0
- package/lib/operations/operation.js +63 -0
- package/lib/operations/options_operation.js +32 -0
- package/lib/operations/profiling_level.js +31 -0
- package/lib/operations/re_index.js +28 -0
- package/lib/operations/remove_user.js +52 -0
- package/lib/operations/rename.js +61 -0
- package/lib/operations/replace_one.js +47 -0
- package/lib/operations/set_profiling_level.js +48 -0
- package/lib/operations/stats.js +45 -0
- package/lib/operations/to_array.js +68 -0
- package/lib/operations/update_many.js +29 -0
- package/lib/operations/update_one.js +44 -0
- package/lib/operations/validate_collection.js +40 -0
- package/lib/read_concern.js +55 -0
- package/lib/topologies/mongos.js +3 -3
- package/lib/topologies/native_topology.js +22 -2
- package/lib/topologies/replset.js +3 -3
- package/lib/topologies/server.js +4 -4
- package/lib/topologies/topology_base.js +6 -6
- package/lib/url_parser.js +4 -3
- package/lib/utils.js +46 -59
- package/lib/write_concern.js +66 -0
- package/package.json +15 -6
- package/lib/.DS_Store +0 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Query = require('../connection/commands').Query;
|
|
4
|
+
const MongoError = require('../error').MongoError;
|
|
5
|
+
const getReadPreference = require('./shared').getReadPreference;
|
|
6
|
+
const collectionNamespace = require('./shared').collectionNamespace;
|
|
7
|
+
const isSharded = require('./shared').isSharded;
|
|
8
|
+
const maxWireVersion = require('../utils').maxWireVersion;
|
|
9
|
+
const applyCommonQueryOptions = require('./shared').applyCommonQueryOptions;
|
|
10
|
+
const command = require('./command');
|
|
11
|
+
|
|
12
|
+
function query(server, ns, cmd, cursorState, options, callback) {
|
|
13
|
+
options = options || {};
|
|
14
|
+
if (cursorState.cursorId != null) {
|
|
15
|
+
return callback();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (cmd == null) {
|
|
19
|
+
return callback(new MongoError(`command ${JSON.stringify(cmd)} does not return a cursor`));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (maxWireVersion(server) < 4) {
|
|
23
|
+
const query = prepareLegacyFindQuery(server, ns, cmd, cursorState, options);
|
|
24
|
+
const queryOptions = applyCommonQueryOptions({}, cursorState);
|
|
25
|
+
if (typeof query.documentsReturnedIn === 'string') {
|
|
26
|
+
queryOptions.documentsReturnedIn = query.documentsReturnedIn;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
server.s.pool.write(query, queryOptions, callback);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const readPreference = getReadPreference(cmd, options);
|
|
34
|
+
const findCmd = prepareFindCommand(server, ns, cmd, cursorState, options);
|
|
35
|
+
|
|
36
|
+
// NOTE: This actually modifies the passed in cmd, and our code _depends_ on this
|
|
37
|
+
// side-effect. Change this ASAP
|
|
38
|
+
cmd.virtual = false;
|
|
39
|
+
|
|
40
|
+
const commandOptions = Object.assign(
|
|
41
|
+
{
|
|
42
|
+
documentsReturnedIn: 'firstBatch',
|
|
43
|
+
numberToReturn: 1,
|
|
44
|
+
slaveOk: readPreference.slaveOk()
|
|
45
|
+
},
|
|
46
|
+
options
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (cmd.readPreference) commandOptions.readPreference = readPreference;
|
|
50
|
+
command(server, ns, findCmd, commandOptions, callback);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function prepareFindCommand(server, ns, cmd, cursorState) {
|
|
54
|
+
cursorState.batchSize = cmd.batchSize || cursorState.batchSize;
|
|
55
|
+
let findCmd = {
|
|
56
|
+
find: collectionNamespace(ns)
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
if (cmd.query) {
|
|
60
|
+
if (cmd.query['$query']) {
|
|
61
|
+
findCmd.filter = cmd.query['$query'];
|
|
62
|
+
} else {
|
|
63
|
+
findCmd.filter = cmd.query;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let sortValue = cmd.sort;
|
|
68
|
+
if (Array.isArray(sortValue)) {
|
|
69
|
+
const sortObject = {};
|
|
70
|
+
|
|
71
|
+
if (sortValue.length > 0 && !Array.isArray(sortValue[0])) {
|
|
72
|
+
let sortDirection = sortValue[1];
|
|
73
|
+
if (sortDirection === 'asc') {
|
|
74
|
+
sortDirection = 1;
|
|
75
|
+
} else if (sortDirection === 'desc') {
|
|
76
|
+
sortDirection = -1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
sortObject[sortValue[0]] = sortDirection;
|
|
80
|
+
} else {
|
|
81
|
+
for (let i = 0; i < sortValue.length; i++) {
|
|
82
|
+
let sortDirection = sortValue[i][1];
|
|
83
|
+
if (sortDirection === 'asc') {
|
|
84
|
+
sortDirection = 1;
|
|
85
|
+
} else if (sortDirection === 'desc') {
|
|
86
|
+
sortDirection = -1;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
sortObject[sortValue[i][0]] = sortDirection;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
sortValue = sortObject;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (cmd.sort) findCmd.sort = sortValue;
|
|
97
|
+
if (cmd.fields) findCmd.projection = cmd.fields;
|
|
98
|
+
if (cmd.hint) findCmd.hint = cmd.hint;
|
|
99
|
+
if (cmd.skip) findCmd.skip = cmd.skip;
|
|
100
|
+
if (cmd.limit) findCmd.limit = cmd.limit;
|
|
101
|
+
if (cmd.limit < 0) {
|
|
102
|
+
findCmd.limit = Math.abs(cmd.limit);
|
|
103
|
+
findCmd.singleBatch = true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (typeof cmd.batchSize === 'number') {
|
|
107
|
+
if (cmd.batchSize < 0) {
|
|
108
|
+
if (cmd.limit !== 0 && Math.abs(cmd.batchSize) < Math.abs(cmd.limit)) {
|
|
109
|
+
findCmd.limit = Math.abs(cmd.batchSize);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
findCmd.singleBatch = true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
findCmd.batchSize = Math.abs(cmd.batchSize);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (cmd.comment) findCmd.comment = cmd.comment;
|
|
119
|
+
if (cmd.maxScan) findCmd.maxScan = cmd.maxScan;
|
|
120
|
+
if (cmd.maxTimeMS) findCmd.maxTimeMS = cmd.maxTimeMS;
|
|
121
|
+
if (cmd.min) findCmd.min = cmd.min;
|
|
122
|
+
if (cmd.max) findCmd.max = cmd.max;
|
|
123
|
+
findCmd.returnKey = cmd.returnKey ? cmd.returnKey : false;
|
|
124
|
+
findCmd.showRecordId = cmd.showDiskLoc ? cmd.showDiskLoc : false;
|
|
125
|
+
if (cmd.snapshot) findCmd.snapshot = cmd.snapshot;
|
|
126
|
+
if (cmd.tailable) findCmd.tailable = cmd.tailable;
|
|
127
|
+
if (cmd.oplogReplay) findCmd.oplogReplay = cmd.oplogReplay;
|
|
128
|
+
if (cmd.noCursorTimeout) findCmd.noCursorTimeout = cmd.noCursorTimeout;
|
|
129
|
+
if (cmd.awaitData) findCmd.awaitData = cmd.awaitData;
|
|
130
|
+
if (cmd.awaitdata) findCmd.awaitData = cmd.awaitdata;
|
|
131
|
+
if (cmd.partial) findCmd.partial = cmd.partial;
|
|
132
|
+
if (cmd.collation) findCmd.collation = cmd.collation;
|
|
133
|
+
if (cmd.readConcern) findCmd.readConcern = cmd.readConcern;
|
|
134
|
+
|
|
135
|
+
// If we have explain, we need to rewrite the find command
|
|
136
|
+
// to wrap it in the explain command
|
|
137
|
+
if (cmd.explain) {
|
|
138
|
+
findCmd = {
|
|
139
|
+
explain: findCmd
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return findCmd;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function prepareLegacyFindQuery(server, ns, cmd, cursorState, options) {
|
|
147
|
+
options = options || {};
|
|
148
|
+
const bson = server.s.bson;
|
|
149
|
+
const readPreference = getReadPreference(cmd, options);
|
|
150
|
+
cursorState.batchSize = cmd.batchSize || cursorState.batchSize;
|
|
151
|
+
|
|
152
|
+
let numberToReturn = 0;
|
|
153
|
+
if (
|
|
154
|
+
cursorState.limit < 0 ||
|
|
155
|
+
(cursorState.limit !== 0 && cursorState.limit < cursorState.batchSize) ||
|
|
156
|
+
(cursorState.limit > 0 && cursorState.batchSize === 0)
|
|
157
|
+
) {
|
|
158
|
+
numberToReturn = cursorState.limit;
|
|
159
|
+
} else {
|
|
160
|
+
numberToReturn = cursorState.batchSize;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const numberToSkip = cursorState.skip || 0;
|
|
164
|
+
|
|
165
|
+
const findCmd = {};
|
|
166
|
+
if (isSharded(server) && readPreference) {
|
|
167
|
+
findCmd['$readPreference'] = readPreference.toJSON();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (cmd.sort) findCmd['$orderby'] = cmd.sort;
|
|
171
|
+
if (cmd.hint) findCmd['$hint'] = cmd.hint;
|
|
172
|
+
if (cmd.snapshot) findCmd['$snapshot'] = cmd.snapshot;
|
|
173
|
+
if (typeof cmd.returnKey !== 'undefined') findCmd['$returnKey'] = cmd.returnKey;
|
|
174
|
+
if (cmd.maxScan) findCmd['$maxScan'] = cmd.maxScan;
|
|
175
|
+
if (cmd.min) findCmd['$min'] = cmd.min;
|
|
176
|
+
if (cmd.max) findCmd['$max'] = cmd.max;
|
|
177
|
+
if (typeof cmd.showDiskLoc !== 'undefined') findCmd['$showDiskLoc'] = cmd.showDiskLoc;
|
|
178
|
+
if (cmd.comment) findCmd['$comment'] = cmd.comment;
|
|
179
|
+
if (cmd.maxTimeMS) findCmd['$maxTimeMS'] = cmd.maxTimeMS;
|
|
180
|
+
if (cmd.explain) {
|
|
181
|
+
// nToReturn must be 0 (match all) or negative (match N and close cursor)
|
|
182
|
+
// nToReturn > 0 will give explain results equivalent to limit(0)
|
|
183
|
+
numberToReturn = -Math.abs(cmd.limit || 0);
|
|
184
|
+
findCmd['$explain'] = true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
findCmd['$query'] = cmd.query;
|
|
188
|
+
if (cmd.readConcern && cmd.readConcern.level !== 'local') {
|
|
189
|
+
throw new MongoError(
|
|
190
|
+
`server find command does not support a readConcern level of ${cmd.readConcern.level}`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (cmd.readConcern) {
|
|
195
|
+
cmd = Object.assign({}, cmd);
|
|
196
|
+
delete cmd['readConcern'];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const serializeFunctions =
|
|
200
|
+
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
|
|
201
|
+
const ignoreUndefined =
|
|
202
|
+
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : false;
|
|
203
|
+
|
|
204
|
+
const query = new Query(bson, ns, findCmd, {
|
|
205
|
+
numberToSkip: numberToSkip,
|
|
206
|
+
numberToReturn: numberToReturn,
|
|
207
|
+
pre32Limit: typeof cmd.limit !== 'undefined' ? cmd.limit : undefined,
|
|
208
|
+
checkKeys: false,
|
|
209
|
+
returnFieldSelector: cmd.fields,
|
|
210
|
+
serializeFunctions: serializeFunctions,
|
|
211
|
+
ignoreUndefined: ignoreUndefined
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (typeof cmd.tailable === 'boolean') query.tailable = cmd.tailable;
|
|
215
|
+
if (typeof cmd.oplogReplay === 'boolean') query.oplogReplay = cmd.oplogReplay;
|
|
216
|
+
if (typeof cmd.noCursorTimeout === 'boolean') query.noCursorTimeout = cmd.noCursorTimeout;
|
|
217
|
+
if (typeof cmd.awaitData === 'boolean') query.awaitData = cmd.awaitData;
|
|
218
|
+
if (typeof cmd.partial === 'boolean') query.partial = cmd.partial;
|
|
219
|
+
|
|
220
|
+
query.slaveOk = readPreference.slaveOk();
|
|
221
|
+
return query;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
module.exports = query;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ReadPreference = require('../topologies/read_preference');
|
|
4
|
+
const MongoError = require('../error').MongoError;
|
|
5
|
+
const ServerType = require('../sdam/server_description').ServerType;
|
|
6
|
+
const TopologyDescription = require('../sdam/topology_description').TopologyDescription;
|
|
7
|
+
|
|
8
|
+
const MESSAGE_HEADER_SIZE = 16;
|
|
9
|
+
const COMPRESSION_DETAILS_SIZE = 9; // originalOpcode + uncompressedSize, compressorID
|
|
10
|
+
|
|
11
|
+
// OPCODE Numbers
|
|
12
|
+
// Defined at https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#request-opcodes
|
|
13
|
+
var opcodes = {
|
|
14
|
+
OP_REPLY: 1,
|
|
15
|
+
OP_UPDATE: 2001,
|
|
16
|
+
OP_INSERT: 2002,
|
|
17
|
+
OP_QUERY: 2004,
|
|
18
|
+
OP_GETMORE: 2005,
|
|
19
|
+
OP_DELETE: 2006,
|
|
20
|
+
OP_KILL_CURSORS: 2007,
|
|
21
|
+
OP_COMPRESSED: 2012,
|
|
22
|
+
OP_MSG: 2013
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
var getReadPreference = function(cmd, options) {
|
|
26
|
+
// Default to command version of the readPreference
|
|
27
|
+
var readPreference = cmd.readPreference || new ReadPreference('primary');
|
|
28
|
+
// If we have an option readPreference override the command one
|
|
29
|
+
if (options.readPreference) {
|
|
30
|
+
readPreference = options.readPreference;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof readPreference === 'string') {
|
|
34
|
+
readPreference = new ReadPreference(readPreference);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!(readPreference instanceof ReadPreference)) {
|
|
38
|
+
throw new MongoError('read preference must be a ReadPreference instance');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return readPreference;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Parses the header of a wire protocol message
|
|
45
|
+
var parseHeader = function(message) {
|
|
46
|
+
return {
|
|
47
|
+
length: message.readInt32LE(0),
|
|
48
|
+
requestId: message.readInt32LE(4),
|
|
49
|
+
responseTo: message.readInt32LE(8),
|
|
50
|
+
opCode: message.readInt32LE(12)
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function applyCommonQueryOptions(queryOptions, options) {
|
|
55
|
+
Object.assign(queryOptions, {
|
|
56
|
+
raw: typeof options.raw === 'boolean' ? options.raw : false,
|
|
57
|
+
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
|
|
58
|
+
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
|
|
59
|
+
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
|
|
60
|
+
monitoring: typeof options.monitoring === 'boolean' ? options.monitoring : false,
|
|
61
|
+
fullResult: typeof options.fullResult === 'boolean' ? options.fullResult : false
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (typeof options.socketTimeout === 'number') {
|
|
65
|
+
queryOptions.socketTimeout = options.socketTimeout;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (options.session) {
|
|
69
|
+
queryOptions.session = options.session;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (typeof options.documentsReturnedIn === 'string') {
|
|
73
|
+
queryOptions.documentsReturnedIn = options.documentsReturnedIn;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return queryOptions;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isSharded(topologyOrServer) {
|
|
80
|
+
if (topologyOrServer.type === 'mongos') return true;
|
|
81
|
+
if (topologyOrServer.description && topologyOrServer.description.type === ServerType.Mongos) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// NOTE: This is incredibly inefficient, and should be removed once command construction
|
|
86
|
+
// happens based on `Server` not `Topology`.
|
|
87
|
+
if (topologyOrServer.description && topologyOrServer.description instanceof TopologyDescription) {
|
|
88
|
+
const servers = Array.from(topologyOrServer.description.servers.values());
|
|
89
|
+
return servers.some(server => server.type === ServerType.Mongos);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function databaseNamespace(ns) {
|
|
96
|
+
return ns.split('.')[0];
|
|
97
|
+
}
|
|
98
|
+
function collectionNamespace(ns) {
|
|
99
|
+
return ns
|
|
100
|
+
.split('.')
|
|
101
|
+
.slice(1)
|
|
102
|
+
.join('.');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
getReadPreference,
|
|
107
|
+
MESSAGE_HEADER_SIZE,
|
|
108
|
+
COMPRESSION_DETAILS_SIZE,
|
|
109
|
+
opcodes,
|
|
110
|
+
parseHeader,
|
|
111
|
+
applyCommonQueryOptions,
|
|
112
|
+
isSharded,
|
|
113
|
+
databaseNamespace,
|
|
114
|
+
collectionNamespace
|
|
115
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MongoError = require('../error').MongoError;
|
|
4
|
+
const collectionNamespace = require('./shared').collectionNamespace;
|
|
5
|
+
const command = require('./command');
|
|
6
|
+
|
|
7
|
+
function writeCommand(server, type, opsField, ns, ops, options, callback) {
|
|
8
|
+
if (ops.length === 0) throw new MongoError(`${type} must contain at least one document`);
|
|
9
|
+
if (typeof options === 'function') {
|
|
10
|
+
callback = options;
|
|
11
|
+
options = {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
options = options || {};
|
|
15
|
+
const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
|
|
16
|
+
const writeConcern = options.writeConcern;
|
|
17
|
+
|
|
18
|
+
const writeCommand = {};
|
|
19
|
+
writeCommand[type] = collectionNamespace(ns);
|
|
20
|
+
writeCommand[opsField] = ops;
|
|
21
|
+
writeCommand.ordered = ordered;
|
|
22
|
+
|
|
23
|
+
if (writeConcern && Object.keys(writeConcern).length > 0) {
|
|
24
|
+
writeCommand.writeConcern = writeConcern;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (options.collation) {
|
|
28
|
+
for (let i = 0; i < writeCommand[opsField].length; i++) {
|
|
29
|
+
if (!writeCommand[opsField][i].collation) {
|
|
30
|
+
writeCommand[opsField][i].collation = options.collation;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (options.bypassDocumentValidation === true) {
|
|
36
|
+
writeCommand.bypassDocumentValidation = options.bypassDocumentValidation;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const commandOptions = Object.assign(
|
|
40
|
+
{
|
|
41
|
+
checkKeys: type === 'insert',
|
|
42
|
+
numberToReturn: 1
|
|
43
|
+
},
|
|
44
|
+
options
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
command(server, ns, writeCommand, commandOptions, callback);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = writeCommand;
|
package/lib/cursor.js
CHANGED
|
@@ -6,18 +6,22 @@ const inherits = require('util').inherits;
|
|
|
6
6
|
const deprecate = require('util').deprecate;
|
|
7
7
|
const handleCallback = require('./utils').handleCallback;
|
|
8
8
|
const SUPPORTS = require('./utils').SUPPORTS;
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const MongoDBNamespace = require('./utils').MongoDBNamespace;
|
|
10
|
+
const ReadPreference = require('./core').ReadPreference;
|
|
11
|
+
const MongoError = require('./core').MongoError;
|
|
11
12
|
const Readable = require('stream').Readable;
|
|
12
|
-
const CoreCursor = require('
|
|
13
|
-
const Map = require('
|
|
14
|
-
const executeOperation = require('./utils').executeOperation;
|
|
13
|
+
const CoreCursor = require('./core').Cursor;
|
|
14
|
+
const Map = require('./core').BSON.Map;
|
|
15
15
|
|
|
16
|
-
const count = require('./operations/cursor_ops').count;
|
|
17
16
|
const each = require('./operations/cursor_ops').each;
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
17
|
+
|
|
18
|
+
const CountOperation = require('./operations/count');
|
|
19
|
+
const ExplainOperation = require('./operations/explain');
|
|
20
|
+
const HasNextOperation = require('./operations/has_next');
|
|
21
|
+
const NextOperation = require('./operations/next');
|
|
22
|
+
const ToArrayOperation = require('./operations/to_array');
|
|
23
|
+
|
|
24
|
+
const executeOperation = require('./operations/execute_operation');
|
|
21
25
|
|
|
22
26
|
/**
|
|
23
27
|
* @fileOverview The **Cursor** class is an internal class that embodies a cursor on MongoDB
|
|
@@ -53,7 +57,7 @@ const toArray = require('./operations/cursor_ops').toArray;
|
|
|
53
57
|
*/
|
|
54
58
|
|
|
55
59
|
/**
|
|
56
|
-
* Namespace provided by the
|
|
60
|
+
* Namespace provided by the code module
|
|
57
61
|
* @external CoreCursor
|
|
58
62
|
* @external Readable
|
|
59
63
|
*/
|
|
@@ -102,10 +106,12 @@ const fields = ['numberOfRetries', 'tailableRetryInterval'];
|
|
|
102
106
|
*
|
|
103
107
|
* collection.find({}).maxTimeMS(1000).maxScan(100).skip(1).toArray(..)
|
|
104
108
|
*/
|
|
105
|
-
function Cursor(
|
|
109
|
+
function Cursor(topology, ns, cmd, options) {
|
|
106
110
|
CoreCursor.apply(this, Array.prototype.slice.call(arguments, 0));
|
|
107
111
|
const state = Cursor.INIT;
|
|
108
112
|
const streamOptions = {};
|
|
113
|
+
const bson = topology.s.bson;
|
|
114
|
+
const topologyOptions = topology.s.options;
|
|
109
115
|
|
|
110
116
|
// Tailable cursor options
|
|
111
117
|
const numberOfRetries = options.numberOfRetries || 5;
|
|
@@ -131,7 +137,7 @@ function Cursor(bson, ns, cmd, options, topology, topologyOptions) {
|
|
|
131
137
|
// BSON
|
|
132
138
|
bson: bson,
|
|
133
139
|
// Namespace
|
|
134
|
-
|
|
140
|
+
namespace: MongoDBNamespace.fromString(ns),
|
|
135
141
|
// Command
|
|
136
142
|
cmd: cmd,
|
|
137
143
|
// Options
|
|
@@ -210,9 +216,6 @@ if (SUPPORTS.ASYNC_ITERATOR) {
|
|
|
210
216
|
|
|
211
217
|
// Map core cursor _next method so we can apply mapping
|
|
212
218
|
Cursor.prototype._next = function() {
|
|
213
|
-
if (this._initImplicitSession) {
|
|
214
|
-
this._initImplicitSession();
|
|
215
|
-
}
|
|
216
219
|
return CoreCursor.prototype.next.apply(this, arguments);
|
|
217
220
|
};
|
|
218
221
|
|
|
@@ -220,11 +223,14 @@ for (let name in CoreCursor.prototype) {
|
|
|
220
223
|
Cursor.prototype[name] = CoreCursor.prototype[name];
|
|
221
224
|
}
|
|
222
225
|
|
|
223
|
-
Cursor.prototype.
|
|
226
|
+
Cursor.prototype._initializeCursor = function(callback) {
|
|
227
|
+
// implicitly create a session if one has not been provided
|
|
224
228
|
if (!this.s.explicitlyIgnoreSession && !this.s.session && this.s.topology.hasSessionSupport()) {
|
|
225
229
|
this.s.session = this.s.topology.startSession({ owner: this });
|
|
226
230
|
this.cursorState.session = this.s.session;
|
|
227
231
|
}
|
|
232
|
+
|
|
233
|
+
CoreCursor.prototype._initializeCursor.apply(this, [callback]);
|
|
228
234
|
};
|
|
229
235
|
|
|
230
236
|
Cursor.prototype._endSession = function() {
|
|
@@ -242,9 +248,9 @@ Cursor.prototype._endSession = function() {
|
|
|
242
248
|
* @return {Promise} returns Promise if no callback passed
|
|
243
249
|
*/
|
|
244
250
|
Cursor.prototype.hasNext = function(callback) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
251
|
+
const hasNextOperation = new HasNextOperation(this);
|
|
252
|
+
|
|
253
|
+
return executeOperation(this.s.topology, hasNextOperation, callback);
|
|
248
254
|
};
|
|
249
255
|
|
|
250
256
|
/**
|
|
@@ -255,9 +261,9 @@ Cursor.prototype.hasNext = function(callback) {
|
|
|
255
261
|
* @return {Promise} returns Promise if no callback passed
|
|
256
262
|
*/
|
|
257
263
|
Cursor.prototype.next = function(callback) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
const nextOperation = new NextOperation(this);
|
|
265
|
+
|
|
266
|
+
return executeOperation(this.s.topology, nextOperation, callback);
|
|
261
267
|
};
|
|
262
268
|
|
|
263
269
|
/**
|
|
@@ -826,9 +832,9 @@ Cursor.prototype.toArray = function(callback) {
|
|
|
826
832
|
});
|
|
827
833
|
}
|
|
828
834
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
835
|
+
const toArrayOperation = new ToArrayOperation(this);
|
|
836
|
+
|
|
837
|
+
return executeOperation(this.s.topology, toArrayOperation, callback);
|
|
832
838
|
};
|
|
833
839
|
|
|
834
840
|
/**
|
|
@@ -866,9 +872,9 @@ Cursor.prototype.count = function(applySkipLimit, opts, callback) {
|
|
|
866
872
|
opts = Object.assign({}, opts, { session: this.s.session });
|
|
867
873
|
}
|
|
868
874
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
875
|
+
const countOperation = new CountOperation(this, applySkipLimit, opts);
|
|
876
|
+
|
|
877
|
+
return executeOperation(this.s.topology, countOperation, callback);
|
|
872
878
|
};
|
|
873
879
|
|
|
874
880
|
/**
|
|
@@ -1001,9 +1007,9 @@ Cursor.prototype.explain = function(callback) {
|
|
|
1001
1007
|
delete this.s.cmd['readConcern'];
|
|
1002
1008
|
}
|
|
1003
1009
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1010
|
+
const explainOperation = new ExplainOperation(this);
|
|
1011
|
+
|
|
1012
|
+
return executeOperation(this.s.topology, explainOperation, callback);
|
|
1007
1013
|
};
|
|
1008
1014
|
|
|
1009
1015
|
Cursor.prototype._read = function() {
|
|
@@ -1074,23 +1080,11 @@ Object.defineProperty(Cursor.prototype, 'readPreference', {
|
|
|
1074
1080
|
Object.defineProperty(Cursor.prototype, 'namespace', {
|
|
1075
1081
|
enumerable: true,
|
|
1076
1082
|
get: function() {
|
|
1077
|
-
if (!this
|
|
1078
|
-
return
|
|
1083
|
+
if (!(this && this.s)) {
|
|
1084
|
+
return;
|
|
1079
1085
|
}
|
|
1080
1086
|
|
|
1081
|
-
|
|
1082
|
-
const ns = this.s.ns || '';
|
|
1083
|
-
const firstDot = ns.indexOf('.');
|
|
1084
|
-
if (firstDot < 0) {
|
|
1085
|
-
return {
|
|
1086
|
-
database: this.s.ns,
|
|
1087
|
-
collection: ''
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
return {
|
|
1091
|
-
database: ns.substr(0, firstDot),
|
|
1092
|
-
collection: ns.substr(firstDot + 1)
|
|
1093
|
-
};
|
|
1087
|
+
return this.s.namespace.toString();
|
|
1094
1088
|
}
|
|
1095
1089
|
});
|
|
1096
1090
|
|