Skip to content

Commit dc42107

Browse files
authored
refactor: remove all internal usage of executeCommand helper
This is a relatively large refactor that involves the following changes: - remove ExecuteDbAdminCommandOperation - remove the remaining legacy index operations, convert them into `CreateIndex`/`CreateIndexes`/`EnsureIndex` operations, and put all index-related operations into a single file - convert find_and_modify to command operation, also merge all FindOneAnd* operations into a single file - remove all internal usage of `executeCommand` helper and the helper itself Note that a copy of `executeCommand` is perserved in the FindAndModifyOperation because a larger refactor is needed to port write commands to the operations layer NODE-2714
1 parent b1c61a9 commit dc42107

28 files changed

+807
-1563
lines changed

src/admin.ts

+12-34
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { applyWriteConcern } from './utils';
22
import AddUserOperation = require('./operations/add_user');
3-
import ExecuteDbAdminCommandOperation = require('./operations/execute_db_admin_command');
43
import RemoveUserOperation = require('./operations/remove_user');
54
import ValidateCollectionOperation = require('./operations/validate_collection');
65
import ListDatabasesOperation = require('./operations/list_databases');
76
import executeOperation = require('./operations/execute_operation');
7+
import { RunCommandOperation } from './operations/run_command';
88

99
/**
1010
* The **Admin** class is an internal class that allows convenient access to
@@ -73,10 +73,12 @@ class Admin {
7373
command(command: object, options?: any, callback?: Function): Promise<void> {
7474
const args = Array.prototype.slice.call(arguments, 1);
7575
callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
76-
options = args.length ? args.shift() : {};
77-
78-
const commandOperation = new ExecuteDbAdminCommandOperation(this.s.db, command, options);
79-
return executeOperation(this.s.db.s.topology, commandOperation, callback);
76+
options = Object.assign({ dbName: 'admin' }, args.length ? args.shift() : {});
77+
return executeOperation(
78+
this.s.db.s.topology,
79+
new RunCommandOperation(this.s.db, command, options),
80+
callback
81+
);
8082
}
8183

8284
/**
@@ -91,10 +93,7 @@ class Admin {
9193
buildInfo(options?: any, callback?: Function): Promise<void> {
9294
if (typeof options === 'function') (callback = options), (options = {});
9395
options = options || {};
94-
95-
const cmd = { buildinfo: 1 };
96-
const buildInfoOperation = new ExecuteDbAdminCommandOperation(this.s.db, cmd, options);
97-
return executeOperation(this.s.db.s.topology, buildInfoOperation, callback);
96+
return this.command({ buildinfo: 1 }, options, callback);
9897
}
9998

10099
/**
@@ -109,10 +108,7 @@ class Admin {
109108
serverInfo(options?: any, callback?: Function): Promise<void> {
110109
if (typeof options === 'function') (callback = options), (options = {});
111110
options = options || {};
112-
113-
const cmd = { buildinfo: 1 };
114-
const serverInfoOperation = new ExecuteDbAdminCommandOperation(this.s.db, cmd, options);
115-
return executeOperation(this.s.db.s.topology, serverInfoOperation, callback);
111+
return this.command({ buildinfo: 1 }, options, callback);
116112
}
117113

118114
/**
@@ -126,14 +122,7 @@ class Admin {
126122
serverStatus(options?: any, callback?: Function): Promise<void> {
127123
if (typeof options === 'function') (callback = options), (options = {});
128124
options = options || {};
129-
130-
const serverStatusOperation = new ExecuteDbAdminCommandOperation(
131-
this.s.db,
132-
{ serverStatus: 1 },
133-
options
134-
);
135-
136-
return executeOperation(this.s.db.s.topology, serverStatusOperation, callback);
125+
return this.command({ serverStatus: 1 }, options, callback);
137126
}
138127

139128
/**
@@ -147,11 +136,7 @@ class Admin {
147136
ping(options?: any, callback?: Function): Promise<void> {
148137
if (typeof options === 'function') (callback = options), (options = {});
149138
options = options || {};
150-
151-
const cmd = { ping: 1 };
152-
153-
const pingOperation = new ExecuteDbAdminCommandOperation(this.s.db, cmd, options);
154-
return executeOperation(this.s.db.s.topology, pingOperation, callback);
139+
return this.command({ ping: 1 }, options, callback);
155140
}
156141

157142
/**
@@ -275,14 +260,7 @@ class Admin {
275260
replSetGetStatus(options?: any, callback?: Function): Promise<void> {
276261
if (typeof options === 'function') (callback = options), (options = {});
277262
options = options || {};
278-
279-
const replSetGetStatusOperation = new ExecuteDbAdminCommandOperation(
280-
this.s.db,
281-
{ replSetGetStatus: 1 },
282-
options
283-
);
284-
285-
return executeOperation(this.s.db.s.topology, replSetGetStatusOperation, callback);
263+
return this.command({ replSetGetStatus: 1 }, options, callback);
286264
}
287265
}
288266

src/collection.ts

+92-32
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import {
1212
checkCollectionName,
1313
deprecateOptions,
1414
executeLegacyOperation,
15-
MongoDBNamespace
15+
MongoDBNamespace,
16+
handleCallback,
17+
applyWriteConcern
1618
} from './utils';
1719
import { ObjectId } from './bson';
1820
import { MongoError } from './error';
@@ -22,32 +24,37 @@ import ChangeStream = require('./change_stream');
2224
import WriteConcern = require('./write_concern');
2325
import ReadConcern = require('./read_concern');
2426
import { AggregationCursor, CommandCursor } from './cursor';
25-
import { ensureIndex, group, save, checkForAtomicOperators } from './operations/collection_ops';
26-
import { removeDocuments, updateDocuments } from './operations/common_functions';
27+
import { removeDocuments, updateDocuments, insertDocuments } from './operations/common_functions';
2728
import AggregateOperation = require('./operations/aggregate');
2829
import BulkWriteOperation = require('./operations/bulk_write');
2930
import CountDocumentsOperation = require('./operations/count_documents');
30-
import CreateIndexesOperation = require('./operations/create_indexes');
31+
import {
32+
CreateIndexesOperation,
33+
CreateIndexOperation,
34+
DropIndexOperation,
35+
DropIndexesOperation,
36+
EnsureIndexOperation,
37+
IndexesOperation,
38+
IndexExistsOperation,
39+
IndexInformationOperation,
40+
ListIndexesOperation
41+
} from './operations/indexes';
3142
import DeleteManyOperation = require('./operations/delete_many');
3243
import DeleteOneOperation = require('./operations/delete_one');
3344
import DistinctOperation = require('./operations/distinct');
3445
import { DropCollectionOperation } from './operations/drop';
35-
import DropIndexOperation = require('./operations/drop_index');
36-
import DropIndexesOperation = require('./operations/drop_indexes');
3746
import EstimatedDocumentCountOperation = require('./operations/estimated_document_count');
3847
import FindOperation = require('./operations/find');
3948
import FindOneOperation = require('./operations/find_one');
40-
import FindAndModifyOperation = require('./operations/find_and_modify');
41-
import FindOneAndDeleteOperation = require('./operations/find_one_and_delete');
42-
import FindOneAndReplaceOperation = require('./operations/find_one_and_replace');
43-
import FindOneAndUpdateOperation = require('./operations/find_one_and_update');
44-
import IndexesOperation = require('./operations/indexes');
45-
import IndexExistsOperation = require('./operations/index_exists');
46-
import IndexInformationOperation = require('./operations/index_information');
49+
import {
50+
FindAndModifyOperation,
51+
FindOneAndDeleteOperation,
52+
FindOneAndReplaceOperation,
53+
FindOneAndUpdateOperation
54+
} from './operations/find_and_modify';
4755
import InsertManyOperation = require('./operations/insert_many');
4856
import InsertOneOperation = require('./operations/insert_one');
4957
import IsCappedOperation = require('./operations/is_capped');
50-
import ListIndexesOperation = require('./operations/list_indexes');
5158
import MapReduceOperation = require('./operations/map_reduce');
5259
import OptionsOperation = require('./operations/options_operation');
5360
import RenameOperation = require('./operations/rename');
@@ -56,6 +63,7 @@ import { CollStatsOperation } from './operations/stats';
5663
import UpdateManyOperation = require('./operations/update_many');
5764
import UpdateOneOperation = require('./operations/update_one');
5865
import executeOperation = require('./operations/execute_operation');
66+
import { EvalGroupOperation, GroupOperation } from './operations/group';
5967
const mergeKeys = ['ignoreUndefined'];
6068

6169
interface Collection {
@@ -199,7 +207,7 @@ class Collection {
199207
* @memberof Collection#
200208
* @readonly
201209
*/
202-
get dbName() {
210+
get dbName(): string {
203211
return this.s.namespace.db;
204212
}
205213

@@ -210,7 +218,7 @@ class Collection {
210218
* @memberof Collection#
211219
* @readonly
212220
*/
213-
get collectionName() {
221+
get collectionName(): string {
214222
return this.s.namespace.collection;
215223
}
216224

@@ -798,7 +806,7 @@ class Collection {
798806
if (typeof options === 'function') (callback = options), (options = {});
799807
options = options || {};
800808

801-
const createIndexesOperation = new CreateIndexesOperation(
809+
const createIndexesOperation = new CreateIndexOperation(
802810
this,
803811
this.collectionName,
804812
fieldOrSpec,
@@ -1971,12 +1979,11 @@ Collection.prototype.ensureIndex = deprecate(function(
19711979
if (typeof options === 'function') (callback = options), (options = {});
19721980
options = options || {};
19731981

1974-
return executeLegacyOperation(this.s.topology, ensureIndex, [
1975-
this,
1976-
fieldOrSpec,
1977-
options,
1982+
return executeOperation(
1983+
this.s.topology,
1984+
new EnsureIndexOperation(this.s.db, this.collectionName, fieldOrSpec, options),
19781985
callback
1979-
]);
1986+
);
19801987
},
19811988
'collection.ensureIndex is deprecated. Use createIndexes instead.');
19821989

@@ -2185,18 +2192,71 @@ Collection.prototype.group = deprecate(function(
21852192
// Set up the command as default
21862193
command = command == null ? true : command;
21872194

2188-
return executeLegacyOperation(this.s.topology, group, [
2189-
this,
2190-
keys,
2191-
condition,
2192-
initial,
2193-
reduce,
2194-
finalize,
2195-
command,
2196-
options,
2195+
if (command == null) {
2196+
return executeOperation(
2197+
this.s.topology,
2198+
new EvalGroupOperation(this, keys, condition, initial, reduce, finalize, options),
2199+
callback
2200+
);
2201+
}
2202+
2203+
return executeOperation(
2204+
this.s.topology,
2205+
new GroupOperation(this, keys, condition, initial, reduce, finalize, options),
21972206
callback
2198-
]);
2207+
);
21992208
},
22002209
'MongoDB 3.6 or higher no longer supports the group command. We recommend rewriting using the aggregation framework.');
22012210

2211+
2212+
// Check the update operation to ensure it has atomic operators.
2213+
function checkForAtomicOperators(update: any): any {
2214+
if (Array.isArray(update)) {
2215+
return update.reduce((err?: any, u?: any) => err || checkForAtomicOperators(u), null);
2216+
}
2217+
2218+
const keys = Object.keys(update);
2219+
2220+
// same errors as the server would give for update doc lacking atomic operators
2221+
if (keys.length === 0) {
2222+
return toError('The update operation document must contain at least one atomic operator.');
2223+
}
2224+
2225+
if (keys[0][0] !== '$') {
2226+
return toError('the update operation document must contain atomic operators.');
2227+
}
2228+
}
2229+
2230+
/**
2231+
* Save a document.
2232+
*
2233+
* @function
2234+
* @param {Collection} coll Collection instance.
2235+
* @param {any} doc Document to save
2236+
* @param {any} [options] Optional settings. See Collection.prototype.save for a list of options.
2237+
* @param {Collection~writeOpCallback} [callback] The command result callback
2238+
* @deprecated use insertOne, insertMany, updateOne or updateMany
2239+
*/
2240+
function save(coll: any, doc: any, options?: any, callback?: Function) {
2241+
// Get the write concern options
2242+
const finalOptions = applyWriteConcern(
2243+
Object.assign({}, options),
2244+
{ db: coll.s.db, collection: coll },
2245+
options
2246+
);
2247+
// Establish if we need to perform an insert or update
2248+
if (doc._id != null) {
2249+
finalOptions.upsert = true;
2250+
return updateDocuments(coll, { _id: doc._id }, doc, finalOptions, callback);
2251+
}
2252+
2253+
// Insert the document
2254+
insertDocuments(coll, [doc], finalOptions, (err?: any, result?: any) => {
2255+
if (callback == null) return;
2256+
if (doc == null) return handleCallback(callback, null, null);
2257+
if (err) return handleCallback(callback, err, null);
2258+
handleCallback(callback, null, result);
2259+
});
2260+
}
2261+
22022262
export = Collection;

0 commit comments

Comments
 (0)