@mikro-orm/mongodb 7.0.0-dev.33 → 7.0.0-dev.331

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.
@@ -1,10 +1,12 @@
1
- import { MongoClient, type ClientSession, type Collection, type Db, type MongoClientOptions, type TransactionOptions } from 'mongodb';
2
- import { Connection, type AnyEntity, type Configuration, type ConnectionOptions, type ConnectionType, type EntityData, type EntityName, type FilterQuery, type IsolationLevel, type QueryOrderMap, type QueryResult, type Transaction, type TransactionEventBroadcaster, type UpsertOptions, type UpsertManyOptions, type LoggingOptions } from '@mikro-orm/core';
1
+ import { type ClientSession, type Collection, type Db, MongoClient, type MongoClientOptions, type TransactionOptions } from 'mongodb';
2
+ import { type AnyEntity, type CollationOptions, type Configuration, Connection, type ConnectionOptions, type ConnectionType, type Dictionary, type EntityData, type EntityName, type FilterQuery, type IsolationLevel, type LoggingOptions, type QueryOrderMap, type QueryResult, type Transaction, type TransactionEventBroadcaster, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
3
3
  export declare class MongoConnection extends Connection {
4
- protected client: MongoClient;
5
- protected db: Db;
4
+ #private;
6
5
  constructor(config: Configuration, options?: ConnectionOptions, type?: ConnectionType);
7
- connect(): Promise<void>;
6
+ connect(options?: {
7
+ skipOnConnect?: boolean;
8
+ }): Promise<void>;
9
+ createClient(): void;
8
10
  close(force?: boolean): Promise<void>;
9
11
  isConnected(): Promise<boolean>;
10
12
  checkConnection(): Promise<{
@@ -15,22 +17,24 @@ export declare class MongoConnection extends Connection {
15
17
  error?: Error;
16
18
  }>;
17
19
  getClient(): MongoClient;
18
- getCollection<T extends object>(name: EntityName<T>): Collection<T>;
20
+ getCollection<T extends object>(name: EntityName<T> | string): Collection<T>;
19
21
  createCollection<T extends object>(name: EntityName<T>): Promise<Collection<T>>;
20
22
  listCollections(): Promise<string[]>;
21
23
  dropCollection(name: EntityName<AnyEntity>): Promise<boolean>;
22
24
  mapOptions(overrides: MongoClientOptions): MongoClientOptions;
23
- getClientUrl(): string;
24
25
  getDb(): Db;
25
26
  execute(query: string): Promise<any>;
26
- find<T extends object>(collection: string, where: FilterQuery<T>, orderBy?: QueryOrderMap<T> | QueryOrderMap<T>[], limit?: number, offset?: number, fields?: string[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions): Promise<EntityData<T>[]>;
27
- insertOne<T extends object>(collection: string, data: Partial<T>, ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
28
- insertMany<T extends object>(collection: string, data: Partial<T>[], ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
29
- updateMany<T extends object>(collection: string, where: FilterQuery<T>, data: Partial<T>, ctx?: Transaction<ClientSession>, upsert?: boolean, upsertOptions?: UpsertOptions<T>): Promise<QueryResult<T>>;
30
- bulkUpdateMany<T extends object>(collection: string, where: FilterQuery<T>[], data: Partial<T>[], ctx?: Transaction<ClientSession>, upsert?: boolean, upsertOptions?: UpsertManyOptions<T>): Promise<QueryResult<T>>;
31
- deleteMany<T extends object>(collection: string, where: FilterQuery<T>, ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
32
- aggregate<T extends object = any>(collection: string, pipeline: any[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions): Promise<T[]>;
33
- countDocuments<T extends object>(collection: string, where: FilterQuery<T>, ctx?: Transaction<ClientSession>): Promise<number>;
27
+ find<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, opts?: MongoFindOptions<T>): Promise<EntityData<T>[]>;
28
+ stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, opts?: MongoFindOptions<T>): AsyncIterableIterator<T>;
29
+ private _find;
30
+ insertOne<T extends object>(entityName: EntityName<T>, data: Partial<T>, ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
31
+ insertMany<T extends object>(entityName: EntityName<T>, data: Partial<T>[], ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
32
+ updateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: Partial<T>, ctx?: Transaction<ClientSession>, upsert?: boolean, upsertOptions?: UpsertOptions<T>): Promise<QueryResult<T>>;
33
+ bulkUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: Partial<T>[], ctx?: Transaction<ClientSession>, upsert?: boolean, upsertOptions?: UpsertManyOptions<T>): Promise<QueryResult<T>>;
34
+ deleteMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
35
+ aggregate<T extends object = any>(entityName: EntityName<T>, pipeline: any[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions): Promise<T[]>;
36
+ streamAggregate<T extends object>(entityName: EntityName<T>, pipeline: any[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions, stream?: boolean): AsyncIterableIterator<T>;
37
+ countDocuments<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, opts?: MongoCountOptions): Promise<number>;
34
38
  transactional<T>(cb: (trx: Transaction<ClientSession>) => Promise<T>, options?: {
35
39
  isolationLevel?: IsolationLevel;
36
40
  ctx?: Transaction<ClientSession>;
@@ -50,3 +54,21 @@ export declare class MongoConnection extends Connection {
50
54
  private getCollectionName;
51
55
  private logObject;
52
56
  }
57
+ export interface MongoQueryOptions {
58
+ collation?: CollationOptions;
59
+ indexHint?: string | Dictionary;
60
+ maxTimeMS?: number;
61
+ allowDiskUse?: boolean;
62
+ }
63
+ export interface MongoFindOptions<T extends object> extends MongoQueryOptions {
64
+ orderBy?: QueryOrderMap<T> | QueryOrderMap<T>[];
65
+ limit?: number;
66
+ offset?: number;
67
+ fields?: string[];
68
+ ctx?: Transaction<ClientSession>;
69
+ loggerContext?: LoggingOptions;
70
+ }
71
+ export interface MongoCountOptions extends Omit<MongoQueryOptions, 'allowDiskUse'> {
72
+ ctx?: Transaction<ClientSession>;
73
+ loggerContext?: LoggingOptions;
74
+ }
@@ -1,58 +1,67 @@
1
- import { ObjectId, MongoClient, } from 'mongodb';
2
- import { inspect } from 'node:util';
3
- import { Connection, EventType, QueryOrder, Utils, ValidationError, } from '@mikro-orm/core';
1
+ import { MongoClient, ObjectId, } from 'mongodb';
2
+ import { Connection, EventType, inspect, QueryOrder, Utils, ValidationError, } from '@mikro-orm/core';
4
3
  export class MongoConnection extends Connection {
5
- client;
6
- db;
4
+ #client;
5
+ #db;
7
6
  constructor(config, options, type = 'write') {
8
7
  super(config, options, type);
9
8
  // @ts-ignore
10
- ObjectId.prototype[inspect.custom] = function () {
9
+ ObjectId.prototype[Symbol.for('nodejs.util.inspect.custom')] = function () {
11
10
  return `ObjectId('${this.toHexString()}')`;
12
11
  };
13
12
  // @ts-ignore
14
- Date.prototype[inspect.custom] = function () {
13
+ Date.prototype[Symbol.for('nodejs.util.inspect.custom')] = function () {
15
14
  return `ISODate('${this.toISOString()}')`;
16
15
  };
17
16
  }
18
- async connect() {
17
+ async connect(options) {
18
+ this.getClient();
19
+ this.connected = true;
20
+ if (options?.skipOnConnect !== true) {
21
+ await this.onConnect();
22
+ }
23
+ }
24
+ createClient() {
19
25
  let driverOptions = this.options.driverOptions ?? this.config.get('driverOptions');
20
26
  if (typeof driverOptions === 'function') {
21
- driverOptions = await driverOptions();
27
+ driverOptions = driverOptions();
22
28
  }
23
29
  if (driverOptions instanceof MongoClient) {
24
30
  this.logger.log('info', 'Reusing MongoClient provided via `driverOptions`');
25
- this.client = driverOptions;
31
+ this.#client = driverOptions;
26
32
  }
27
33
  else {
28
- this.client = new MongoClient(this.config.getClientUrl(), this.mapOptions(driverOptions));
29
- await this.client.connect();
34
+ this.#client = new MongoClient(this.config.get('clientUrl'), this.mapOptions(driverOptions));
35
+ this.#client.appendMetadata({
36
+ name: 'MikroORM',
37
+ version: Utils.getORMVersion(),
38
+ });
30
39
  const onCreateConnection = this.options.onCreateConnection ?? this.config.get('onCreateConnection');
31
- /* v8 ignore next 3 */
32
- this.client.on('connectionCreated', () => {
33
- void onCreateConnection?.(this.client);
40
+ /* v8 ignore next */
41
+ this.#client.on('connectionCreated', () => {
42
+ void onCreateConnection?.(this.#client);
34
43
  });
35
44
  }
36
- this.db = this.client.db(this.config.get('dbName'));
37
- this.connected = true;
45
+ this.#db = this.#client.db(this.config.get('dbName'));
38
46
  }
39
47
  async close(force) {
40
- await this.client?.close(!!force);
48
+ await this.#client?.close(force);
41
49
  this.connected = false;
50
+ this.#client = undefined;
42
51
  }
43
52
  async isConnected() {
44
53
  try {
45
- const res = await this.db?.command({ ping: 1 });
46
- return this.connected = !!res.ok;
54
+ const res = await this.#db?.command({ ping: 1 });
55
+ return (this.connected = !!res?.ok);
47
56
  }
48
57
  catch (error) {
49
- return this.connected = false;
58
+ return (this.connected = false);
50
59
  }
51
60
  }
52
61
  async checkConnection() {
53
62
  try {
54
- const res = await this.db?.command({ ping: 1 });
55
- return res.ok
63
+ const res = await this.#db?.command({ ping: 1 });
64
+ return res?.ok
56
65
  ? { ok: true }
57
66
  : { ok: false, reason: 'Ping reply does not feature "ok" property, or it evaluates to "false"' };
58
67
  }
@@ -61,20 +70,23 @@ export class MongoConnection extends Connection {
61
70
  }
62
71
  }
63
72
  getClient() {
64
- return this.client;
73
+ if (!this.#client) {
74
+ this.createClient();
75
+ }
76
+ return this.#client;
65
77
  }
66
78
  getCollection(name) {
67
- return this.db.collection(this.getCollectionName(name));
79
+ return this.getDb().collection(this.getCollectionName(name));
68
80
  }
69
81
  async createCollection(name) {
70
- return this.db.createCollection(this.getCollectionName(name));
82
+ return this.getDb().createCollection(this.getCollectionName(name));
71
83
  }
72
84
  async listCollections() {
73
- const collections = await this.db.listCollections({}, { nameOnly: true }).toArray();
85
+ const collections = await this.getDb().listCollections({}, { nameOnly: true }).toArray();
74
86
  return collections.map(c => c.name);
75
87
  }
76
88
  async dropCollection(name) {
77
- return this.db.dropCollection(this.getCollectionName(name));
89
+ return this.getDb().dropCollection(this.getCollectionName(name));
78
90
  }
79
91
  mapOptions(overrides) {
80
92
  const ret = {};
@@ -90,89 +102,120 @@ export class MongoConnection extends Connection {
90
102
  ret.minPoolSize = pool.min;
91
103
  ret.maxPoolSize = pool.max;
92
104
  ret.waitQueueTimeoutMS = pool.idleTimeoutMillis;
93
- ret.driverInfo = {
94
- name: 'MikroORM',
95
- version: Utils.getORMVersion(),
96
- };
97
105
  return Utils.mergeConfig(ret, overrides);
98
106
  }
99
- getClientUrl() {
100
- const options = this.mapOptions(this.options.driverOptions ?? {});
101
- const clientUrl = this.config.getClientUrl(true);
102
- const match = clientUrl.match(/^(\w+):\/\/((.*@.+)|.+)$/);
103
- return match ? `${match[1]}://${options.auth ? options.auth.username + ':*****@' : ''}${match[2]}` : clientUrl;
104
- }
105
107
  getDb() {
106
- return this.db;
108
+ this.#db ??= this.getClient().db(this.config.get('dbName'));
109
+ return this.#db;
107
110
  }
108
111
  async execute(query) {
109
112
  throw new Error(`${this.constructor.name} does not support generic execute method`);
110
113
  }
111
- async find(collection, where, orderBy, limit, offset, fields, ctx, loggerContext) {
114
+ async find(entityName, where, opts = {}) {
115
+ const { cursor, query } = await this._find(entityName, where, opts);
116
+ const now = Date.now();
117
+ const res = await cursor.toArray();
118
+ this.logQuery(`${query}.toArray();`, { took: Date.now() - now, results: res.length, ...opts.loggerContext });
119
+ return res;
120
+ }
121
+ async *stream(entityName, where, opts = {}) {
122
+ const { cursor, query } = await this._find(entityName, where, opts);
123
+ this.logQuery(`${query}.toArray();`, opts.loggerContext);
124
+ yield* cursor;
125
+ }
126
+ async _find(entityName, where, opts = {}) {
112
127
  await this.ensureConnection();
113
- collection = this.getCollectionName(collection);
114
- const options = ctx ? { session: ctx } : {};
115
- if (fields) {
116
- options.projection = fields.reduce((o, k) => Object.assign(o, { [k]: 1 }), {});
128
+ const collection = this.getCollectionName(entityName);
129
+ const options = opts.ctx ? { session: opts.ctx } : {};
130
+ if (opts.fields) {
131
+ options.projection = opts.fields.reduce((o, k) => Object.assign(o, { [k]: 1 }), {});
132
+ }
133
+ if (opts.collation) {
134
+ options.collation = opts.collation;
135
+ }
136
+ if (opts.indexHint != null) {
137
+ options.hint = opts.indexHint;
138
+ }
139
+ if (opts.maxTimeMS != null) {
140
+ options.maxTimeMS = opts.maxTimeMS;
117
141
  }
118
- const resultSet = this.getCollection(collection).find(where, options);
142
+ if (opts.allowDiskUse != null) {
143
+ options.allowDiskUse = opts.allowDiskUse;
144
+ }
145
+ const resultSet = this.getCollection(entityName).find(where, options);
119
146
  let query = `db.getCollection('${collection}').find(${this.logObject(where)}, ${this.logObject(options)})`;
120
- orderBy = Utils.asArray(orderBy);
121
- if (Array.isArray(orderBy) && orderBy.length > 0) {
147
+ const orderBy = Utils.asArray(opts.orderBy);
148
+ if (orderBy.length > 0) {
122
149
  const orderByTuples = [];
123
150
  orderBy.forEach(o => {
124
151
  Utils.keys(o).forEach(k => {
125
152
  const direction = o[k];
126
- orderByTuples.push([k.toString(), Utils.isString(direction) ? direction.toUpperCase() === QueryOrder.ASC ? 1 : -1 : direction]);
153
+ if (typeof direction === 'string') {
154
+ orderByTuples.push([k.toString(), direction.toUpperCase() === QueryOrder.ASC ? 1 : -1]);
155
+ }
156
+ else {
157
+ orderByTuples.push([k.toString(), direction]);
158
+ }
127
159
  });
128
160
  });
129
161
  if (orderByTuples.length > 0) {
130
162
  query += `.sort(${this.logObject(orderByTuples)})`;
131
- // @ts-expect-error ??
132
163
  resultSet.sort(orderByTuples);
133
164
  }
134
165
  }
135
- if (limit !== undefined) {
136
- query += `.limit(${limit})`;
137
- resultSet.limit(limit);
166
+ if (opts.limit !== undefined) {
167
+ query += `.limit(${opts.limit})`;
168
+ resultSet.limit(opts.limit);
138
169
  }
139
- if (offset !== undefined) {
140
- query += `.skip(${offset})`;
141
- resultSet.skip(offset);
170
+ if (opts.offset !== undefined) {
171
+ query += `.skip(${opts.offset})`;
172
+ resultSet.skip(opts.offset);
142
173
  }
143
- const now = Date.now();
144
- const res = await resultSet.toArray();
145
- this.logQuery(`${query}.toArray();`, { took: Date.now() - now, results: res.length, ...loggerContext });
146
- return res;
174
+ return { cursor: resultSet, query };
147
175
  }
148
- async insertOne(collection, data, ctx) {
149
- return this.runQuery('insertOne', collection, data, undefined, ctx);
176
+ async insertOne(entityName, data, ctx) {
177
+ return this.runQuery('insertOne', entityName, data, undefined, ctx);
150
178
  }
151
- async insertMany(collection, data, ctx) {
152
- return this.runQuery('insertMany', collection, data, undefined, ctx);
179
+ async insertMany(entityName, data, ctx) {
180
+ return this.runQuery('insertMany', entityName, data, undefined, ctx);
153
181
  }
154
- async updateMany(collection, where, data, ctx, upsert, upsertOptions) {
155
- return this.runQuery('updateMany', collection, data, where, ctx, upsert, upsertOptions);
182
+ async updateMany(entityName, where, data, ctx, upsert, upsertOptions) {
183
+ return this.runQuery('updateMany', entityName, data, where, ctx, { upsert, upsertOptions });
156
184
  }
157
- async bulkUpdateMany(collection, where, data, ctx, upsert, upsertOptions) {
158
- return this.runQuery('bulkUpdateMany', collection, data, where, ctx, upsert, upsertOptions);
185
+ async bulkUpdateMany(entityName, where, data, ctx, upsert, upsertOptions) {
186
+ return this.runQuery('bulkUpdateMany', entityName, data, where, ctx, { upsert, upsertOptions });
159
187
  }
160
- async deleteMany(collection, where, ctx) {
161
- return this.runQuery('deleteMany', collection, undefined, where, ctx);
188
+ async deleteMany(entityName, where, ctx) {
189
+ return this.runQuery('deleteMany', entityName, undefined, where, ctx);
162
190
  }
163
- async aggregate(collection, pipeline, ctx, loggerContext) {
191
+ async aggregate(entityName, pipeline, ctx, loggerContext) {
164
192
  await this.ensureConnection();
165
- collection = this.getCollectionName(collection);
193
+ const collection = this.getCollectionName(entityName);
166
194
  /* v8 ignore next */
167
195
  const options = ctx ? { session: ctx } : {};
168
196
  const query = `db.getCollection('${collection}').aggregate(${this.logObject(pipeline)}, ${this.logObject(options)}).toArray();`;
169
197
  const now = Date.now();
170
- const res = await this.getCollection(collection).aggregate(pipeline, options).toArray();
198
+ const res = await this.getCollection(entityName).aggregate(pipeline, options).toArray();
171
199
  this.logQuery(query, { took: Date.now() - now, results: res.length, ...loggerContext });
172
200
  return res;
173
201
  }
174
- async countDocuments(collection, where, ctx) {
175
- return this.runQuery('countDocuments', collection, undefined, where, ctx);
202
+ async *streamAggregate(entityName, pipeline, ctx, loggerContext, stream = false) {
203
+ await this.ensureConnection();
204
+ const collection = this.getCollectionName(entityName);
205
+ /* v8 ignore next */
206
+ const options = ctx ? { session: ctx } : {};
207
+ const query = `db.getCollection('${collection}').aggregate(${this.logObject(pipeline)}, ${this.logObject(options)})};`;
208
+ const cursor = this.getCollection(entityName).aggregate(pipeline, options);
209
+ this.logQuery(query, { ...loggerContext });
210
+ yield* cursor;
211
+ }
212
+ async countDocuments(entityName, where, opts = {}) {
213
+ return this.runQuery('countDocuments', entityName, undefined, where, opts.ctx, {
214
+ loggerContext: opts.loggerContext,
215
+ collation: opts.collation,
216
+ indexHint: opts.indexHint,
217
+ maxTimeMS: opts.maxTimeMS,
218
+ });
176
219
  }
177
220
  async transactional(cb, options = {}) {
178
221
  await this.ensureConnection();
@@ -196,7 +239,7 @@ export class MongoConnection extends Connection {
196
239
  if (!ctx) {
197
240
  await eventBroadcaster?.dispatchEvent(EventType.beforeTransactionStart);
198
241
  }
199
- const session = ctx || this.client.startSession();
242
+ const session = ctx || this.getClient().startSession();
200
243
  session.startTransaction(txOptions);
201
244
  this.logQuery('db.begin();');
202
245
  await eventBroadcaster?.dispatchEvent(EventType.afterTransactionStart, session);
@@ -216,9 +259,10 @@ export class MongoConnection extends Connection {
216
259
  this.logQuery('db.rollback();');
217
260
  await eventBroadcaster?.dispatchEvent(EventType.afterTransactionRollback, ctx);
218
261
  }
219
- async runQuery(method, collection, data, where, ctx, upsert, upsertOptions, loggerContext) {
262
+ async runQuery(method, entityName, data, where, ctx, opts) {
220
263
  await this.ensureConnection();
221
- collection = this.getCollectionName(collection);
264
+ const { upsert, upsertOptions, loggerContext, collation, indexHint, maxTimeMS } = opts ?? {};
265
+ const collection = this.getCollectionName(entityName);
222
266
  const logger = this.config.getLogger();
223
267
  const options = ctx ? { session: ctx, upsert } : { upsert };
224
268
  if (options.upsert === undefined) {
@@ -227,27 +271,33 @@ export class MongoConnection extends Connection {
227
271
  const now = Date.now();
228
272
  let res;
229
273
  let query;
230
- const log = (msg) => logger.isEnabled('query') ? msg() : '';
274
+ const log = (msg) => (logger.isEnabled('query') ? msg() : '');
231
275
  switch (method) {
232
276
  case 'insertOne':
233
- Object.keys(data).filter(k => typeof data[k] === 'undefined').forEach(k => delete data[k]);
277
+ Object.keys(data)
278
+ .filter(k => typeof data[k] === 'undefined')
279
+ .forEach(k => delete data[k]);
234
280
  query = log(() => `db.getCollection('${collection}').insertOne(${this.logObject(data)}, ${this.logObject(options)});`);
235
- res = await this.rethrow(this.getCollection(collection).insertOne(data, options), query);
281
+ res = await this.rethrow(this.getCollection(entityName).insertOne(data, options), query);
236
282
  break;
237
283
  case 'insertMany':
238
- data.forEach(data => Object.keys(data).filter(k => typeof data[k] === 'undefined').forEach(k => delete data[k]));
284
+ data.forEach(data => Object.keys(data)
285
+ .filter(k => typeof data[k] === 'undefined')
286
+ .forEach(k => delete data[k]));
239
287
  query = log(() => `db.getCollection('${collection}').insertMany(${this.logObject(data)}, ${this.logObject(options)});`);
240
- res = await this.rethrow(this.getCollection(collection).insertMany(data, options), query);
288
+ res = await this.rethrow(this.getCollection(entityName).insertMany(data, options), query);
241
289
  break;
242
290
  case 'updateMany': {
243
- const payload = Object.keys(data).some(k => k.startsWith('$')) ? data : this.createUpdatePayload(data, upsertOptions);
291
+ const payload = Object.keys(data).every(k => k.startsWith('$'))
292
+ ? data
293
+ : this.createUpdatePayload(data, upsertOptions);
244
294
  query = log(() => `db.getCollection('${collection}').updateMany(${this.logObject(where)}, ${this.logObject(payload)}, ${this.logObject(options)});`);
245
- res = await this.rethrow(this.getCollection(collection).updateMany(where, payload, options), query);
295
+ res = (await this.rethrow(this.getCollection(entityName).updateMany(where, payload, options), query));
246
296
  break;
247
297
  }
248
298
  case 'bulkUpdateMany': {
249
299
  query = log(() => `bulk = db.getCollection('${collection}').initializeUnorderedBulkOp(${this.logObject(options)});\n`);
250
- const bulk = this.getCollection(collection).initializeUnorderedBulkOp(options);
300
+ const bulk = this.getCollection(entityName).initializeUnorderedBulkOp(options);
251
301
  data.forEach((row, idx) => {
252
302
  const id = where[idx];
253
303
  const cond = Utils.isPlainObject(id) ? id : { _id: id };
@@ -272,8 +322,19 @@ export class MongoConnection extends Connection {
272
322
  }
273
323
  case 'deleteMany':
274
324
  case 'countDocuments':
325
+ if (method === 'countDocuments') {
326
+ if (collation) {
327
+ options.collation = collation;
328
+ }
329
+ if (indexHint != null) {
330
+ options.hint = indexHint;
331
+ }
332
+ if (maxTimeMS != null) {
333
+ options.maxTimeMS = maxTimeMS;
334
+ }
335
+ }
275
336
  query = log(() => `db.getCollection('${collection}').${method}(${this.logObject(where)}, ${this.logObject(options)});`);
276
- res = await this.rethrow(this.getCollection(collection)[method](where, options), query);
337
+ res = await this.rethrow(this.getCollection(entityName)[method](where, options), query);
277
338
  break;
278
339
  }
279
340
  this.logQuery(query, { took: Date.now() - now, ...loggerContext });
@@ -290,7 +351,14 @@ export class MongoConnection extends Connection {
290
351
  });
291
352
  }
292
353
  createUpdatePayload(row, upsertOptions) {
354
+ row = { ...row };
293
355
  const doc = { $set: row };
356
+ Utils.keys(row).forEach(k => {
357
+ if (k.toString().startsWith('$')) {
358
+ doc[k] = row[k];
359
+ delete row[k];
360
+ }
361
+ });
294
362
  const $unset = {};
295
363
  const $inc = {};
296
364
  for (const k of Utils.keys(row)) {
@@ -346,13 +414,12 @@ export class MongoConnection extends Connection {
346
414
  insertedIds: res.insertedIds ? Object.values(res.insertedIds) : undefined,
347
415
  };
348
416
  }
349
- getCollectionName(name) {
350
- name = Utils.className(name);
351
- const meta = this.metadata.find(name);
352
- return meta ? meta.collection : name;
417
+ getCollectionName(entityName) {
418
+ const meta = this.metadata.find(entityName);
419
+ return meta ? meta.collection : Utils.className(entityName);
353
420
  }
354
421
  logObject(o) {
355
- if (o.session) {
422
+ if (o?.session) {
356
423
  o = { ...o, session: `[ClientSession]` };
357
424
  }
358
425
  return inspect(o, { depth: 5, compact: true, breakLength: 300 });
package/MongoDriver.d.ts CHANGED
@@ -1,30 +1,39 @@
1
1
  import { type ClientSession } from 'mongodb';
2
- import { type Configuration, type CountOptions, DatabaseDriver, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type FilterQuery, type FindOneOptions, type FindOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type PopulateOptions, type PopulatePath, type QueryResult, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
2
+ import { type Configuration, type Constructor, type CountOptions, DatabaseDriver, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type EntityName, type FilterQuery, type FindOneOptions, type FindOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type PopulateOptions, type PopulatePath, type QueryResult, type StreamOptions, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
3
3
  import { MongoConnection } from './MongoConnection.js';
4
4
  import { MongoPlatform } from './MongoPlatform.js';
5
5
  import { MongoEntityManager } from './MongoEntityManager.js';
6
+ import { MongoMikroORM } from './MongoMikroORM.js';
6
7
  export declare class MongoDriver extends DatabaseDriver<MongoConnection> {
7
8
  [EntityManagerType]: MongoEntityManager<this>;
8
9
  protected readonly connection: MongoConnection;
9
10
  protected readonly platform: MongoPlatform;
10
11
  constructor(config: Configuration);
11
12
  createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
12
- find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
13
- findOne<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
14
- findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
15
- count<T extends object>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T>, ctx?: Transaction<ClientSession>): Promise<number>;
16
- nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
17
- nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
18
- nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T> & UpsertOptions<T>): Promise<QueryResult<T>>;
19
- nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
20
- nativeDelete<T extends object>(entityName: string, where: FilterQuery<T>, options?: {
13
+ stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T, any, any, any> & {
14
+ rawResults?: boolean;
15
+ }): AsyncIterableIterator<T>;
16
+ find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
17
+ findOne<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
18
+ findVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
19
+ streamVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): AsyncIterableIterator<EntityData<T>>;
20
+ count<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: CountOptions<T>): Promise<number>;
21
+ nativeInsert<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
22
+ nativeInsertMany<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
23
+ nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T> & UpsertOptions<T>): Promise<QueryResult<T>>;
24
+ nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
25
+ nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: {
21
26
  ctx?: Transaction<ClientSession>;
22
27
  }): Promise<QueryResult<T>>;
23
- aggregate(entityName: string, pipeline: any[], ctx?: Transaction<ClientSession>): Promise<any[]>;
28
+ aggregate(entityName: EntityName, pipeline: any[], ctx?: Transaction<ClientSession>): Promise<any[]>;
29
+ streamAggregate<T extends object>(entityName: EntityName<T>, pipeline: any[], ctx?: Transaction<ClientSession>): AsyncIterableIterator<T>;
24
30
  getPlatform(): MongoPlatform;
31
+ private buildQueryOptions;
25
32
  private renameFields;
26
33
  private convertObjectIds;
27
34
  private buildFilterById;
28
- protected buildFields<T extends object, P extends string = never>(entityName: string, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, P>[], exclude?: string[]): string[] | undefined;
35
+ protected buildFields<T extends object, P extends string = never>(entityName: EntityName<T>, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, P>[], exclude?: string[]): string[] | undefined;
29
36
  private handleVersionProperty;
37
+ /** @inheritDoc */
38
+ getORMClass(): Constructor<MongoMikroORM>;
30
39
  }