@mikro-orm/mongodb 7.0.5-dev.8 → 7.0.5
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/MongoConnection.d.ts +143 -62
- package/MongoConnection.js +425 -420
- package/MongoDriver.d.ts +104 -32
- package/MongoDriver.js +431 -421
- package/MongoEntityManager.d.ts +44 -26
- package/MongoEntityManager.js +42 -42
- package/MongoEntityRepository.d.ts +11 -11
- package/MongoEntityRepository.js +20 -20
- package/MongoExceptionConverter.d.ts +4 -4
- package/MongoExceptionConverter.js +13 -13
- package/MongoMikroORM.d.ts +55 -16
- package/MongoMikroORM.js +22 -22
- package/MongoPlatform.d.ts +39 -24
- package/MongoPlatform.js +83 -83
- package/MongoSchemaGenerator.d.ts +24 -26
- package/MongoSchemaGenerator.js +213 -209
- package/README.md +1 -1
- package/index.d.ts +5 -1
- package/index.js +1 -1
- package/package.json +3 -3
package/MongoDriver.js
CHANGED
|
@@ -1,444 +1,454 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
|
-
import { DatabaseDriver, EntityManagerType, PolymorphicRef, ReferenceKind, Utils
|
|
2
|
+
import { DatabaseDriver, EntityManagerType, PolymorphicRef, ReferenceKind, Utils } 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
6
|
import { MongoMikroORM } from './MongoMikroORM.js';
|
|
7
7
|
/** Database driver for MongoDB. */
|
|
8
8
|
export class MongoDriver extends DatabaseDriver {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
const fields = this.buildFields(entityName, options.populate || [], options.fields, options.exclude);
|
|
25
|
-
where = this.renameFields(entityName, where, true);
|
|
26
|
-
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
27
|
-
const res = this.getConnection('read').stream(entityName, where, {
|
|
28
|
-
orderBy,
|
|
29
|
-
limit: options.limit,
|
|
30
|
-
offset: options.offset,
|
|
31
|
-
fields,
|
|
32
|
-
ctx: options.ctx,
|
|
33
|
-
...this.buildQueryOptions(options),
|
|
34
|
-
});
|
|
35
|
-
for await (const item of res) {
|
|
36
|
-
if (options.rawResults) {
|
|
37
|
-
yield item;
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
yield this.mapResult(item, this.metadata.find(entityName));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
9
|
+
[EntityManagerType];
|
|
10
|
+
connection = new MongoConnection(this.config);
|
|
11
|
+
platform = new MongoPlatform();
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super(config, ['mongodb']);
|
|
14
|
+
}
|
|
15
|
+
createEntityManager(useContext) {
|
|
16
|
+
const EntityManagerClass = this.config.get('entityManager', MongoEntityManager);
|
|
17
|
+
return new EntityManagerClass(this.config, this, this.metadata, useContext);
|
|
18
|
+
}
|
|
19
|
+
async *stream(entityName, where, options) {
|
|
20
|
+
if (this.metadata.find(entityName)?.virtual) {
|
|
21
|
+
yield* this.streamVirtual(entityName, where, options);
|
|
22
|
+
return;
|
|
43
23
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
62
|
-
const meta = this.metadata.find(entityName);
|
|
63
|
-
const { orderBy: newOrderBy, where: newWhere } = this.processCursorOptions(meta, options, options.orderBy);
|
|
64
|
-
const newWhereConverted = this.renameFields(entityName, newWhere, true);
|
|
65
|
-
const orderBy = Utils.asArray(newOrderBy).map(order => this.renameFields(entityName, order, true));
|
|
66
|
-
const res = await this.rethrow(this.getConnection('read').find(entityName, andWhere(where, newWhereConverted), {
|
|
67
|
-
orderBy,
|
|
68
|
-
limit: options.limit,
|
|
69
|
-
offset: options.offset,
|
|
70
|
-
fields,
|
|
71
|
-
ctx: options.ctx,
|
|
72
|
-
loggerContext: options.logging,
|
|
73
|
-
...this.buildQueryOptions(options),
|
|
74
|
-
}));
|
|
75
|
-
if (isCursorPagination && !first && !!last) {
|
|
76
|
-
res.reverse();
|
|
77
|
-
}
|
|
78
|
-
return res.map(r => this.mapResult(r, this.metadata.find(entityName)));
|
|
79
|
-
}
|
|
80
|
-
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
81
|
-
const res = await this.rethrow(this.getConnection('read').find(entityName, where, {
|
|
82
|
-
orderBy,
|
|
83
|
-
limit: options.limit,
|
|
84
|
-
offset: options.offset,
|
|
85
|
-
fields,
|
|
86
|
-
ctx: options.ctx,
|
|
87
|
-
...this.buildQueryOptions(options),
|
|
88
|
-
}));
|
|
89
|
-
return res.map(r => this.mapResult(r, this.metadata.find(entityName)));
|
|
90
|
-
}
|
|
91
|
-
async findOne(entityName, where, options = { populate: [], orderBy: {} }) {
|
|
92
|
-
if (this.metadata.find(entityName)?.virtual) {
|
|
93
|
-
const [item] = await this.findVirtual(entityName, where, options);
|
|
94
|
-
/* v8 ignore next */
|
|
95
|
-
return item ?? null;
|
|
96
|
-
}
|
|
97
|
-
if (Utils.isPrimaryKey(where)) {
|
|
98
|
-
where = this.buildFilterById(entityName, where);
|
|
99
|
-
}
|
|
100
|
-
const fields = this.buildFields(entityName, options.populate || [], options.fields, options.exclude);
|
|
101
|
-
where = this.renameFields(entityName, where, true);
|
|
102
|
-
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
103
|
-
const res = await this.rethrow(this.getConnection('read').find(entityName, where, {
|
|
104
|
-
orderBy,
|
|
105
|
-
limit: 1,
|
|
106
|
-
fields,
|
|
107
|
-
ctx: options.ctx,
|
|
108
|
-
loggerContext: options.logging,
|
|
109
|
-
...this.buildQueryOptions(options),
|
|
110
|
-
}));
|
|
111
|
-
return this.mapResult(res[0], this.metadata.find(entityName));
|
|
112
|
-
}
|
|
113
|
-
async findVirtual(entityName, where, options) {
|
|
114
|
-
const meta = this.metadata.find(entityName);
|
|
115
|
-
if (meta.expression instanceof Function) {
|
|
116
|
-
const em = this.createEntityManager();
|
|
117
|
-
return meta.expression(em, where, options);
|
|
118
|
-
}
|
|
119
|
-
/* v8 ignore next */
|
|
120
|
-
return super.findVirtual(entityName, where, options);
|
|
121
|
-
}
|
|
122
|
-
async *streamVirtual(entityName, where, options) {
|
|
123
|
-
const meta = this.metadata.find(entityName);
|
|
124
|
-
if (meta.expression instanceof Function) {
|
|
125
|
-
const em = this.createEntityManager();
|
|
126
|
-
const stream = await meta.expression(em, where, options, true);
|
|
127
|
-
yield* stream;
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
/* v8 ignore next */
|
|
131
|
-
return super.findVirtual(entityName, where, options);
|
|
24
|
+
const fields = this.buildFields(entityName, options.populate || [], options.fields, options.exclude);
|
|
25
|
+
where = this.renameFields(entityName, where, true);
|
|
26
|
+
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
27
|
+
const res = this.getConnection('read').stream(entityName, where, {
|
|
28
|
+
orderBy,
|
|
29
|
+
limit: options.limit,
|
|
30
|
+
offset: options.offset,
|
|
31
|
+
fields,
|
|
32
|
+
ctx: options.ctx,
|
|
33
|
+
...this.buildQueryOptions(options),
|
|
34
|
+
});
|
|
35
|
+
for await (const item of res) {
|
|
36
|
+
if (options.rawResults) {
|
|
37
|
+
yield item;
|
|
38
|
+
} else {
|
|
39
|
+
yield this.mapResult(item, this.metadata.find(entityName));
|
|
40
|
+
}
|
|
132
41
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
where = this.renameFields(entityName, where, true);
|
|
139
|
-
const queryOpts = this.buildQueryOptions(options);
|
|
140
|
-
return this.rethrow(this.getConnection('read').countDocuments(entityName, where, {
|
|
141
|
-
ctx: options.ctx,
|
|
142
|
-
loggerContext: options.logging,
|
|
143
|
-
...queryOpts,
|
|
144
|
-
}));
|
|
145
|
-
}
|
|
146
|
-
async nativeInsert(entityName, data, options = {}) {
|
|
147
|
-
this.handleVersionProperty(entityName, data);
|
|
148
|
-
data = this.renameFields(entityName, data);
|
|
149
|
-
return this.rethrow(this.getConnection('write').insertOne(entityName, data, options.ctx));
|
|
150
|
-
}
|
|
151
|
-
async nativeInsertMany(entityName, data, options = {}) {
|
|
152
|
-
data = data.map(item => {
|
|
153
|
-
this.handleVersionProperty(entityName, item);
|
|
154
|
-
return this.renameFields(entityName, item);
|
|
155
|
-
});
|
|
156
|
-
const meta = this.metadata.find(entityName);
|
|
157
|
-
/* v8 ignore next */
|
|
158
|
-
const pk = meta?.getPrimaryProps()[0].fieldNames[0] ?? '_id';
|
|
159
|
-
const res = await this.rethrow(this.getConnection('write').insertMany(entityName, data, options.ctx));
|
|
160
|
-
res.rows = res.insertedIds.map(id => ({ [pk]: id }));
|
|
161
|
-
return res;
|
|
162
|
-
}
|
|
163
|
-
async nativeUpdate(entityName, where, data, options = {}) {
|
|
164
|
-
if (Utils.isPrimaryKey(where)) {
|
|
165
|
-
where = this.buildFilterById(entityName, where);
|
|
166
|
-
}
|
|
167
|
-
this.handleVersionProperty(entityName, data, true);
|
|
168
|
-
data = this.renameFields(entityName, data);
|
|
169
|
-
where = this.renameFields(entityName, where, true);
|
|
170
|
-
options = { ...options };
|
|
171
|
-
const meta = this.metadata.find(entityName);
|
|
172
|
-
/* v8 ignore next */
|
|
173
|
-
const rename = (field) => meta ? (meta.properties[field]?.fieldNames[0] ?? field) : field;
|
|
174
|
-
if (options.onConflictFields && Array.isArray(options.onConflictFields)) {
|
|
175
|
-
options.onConflictFields = options.onConflictFields.map(rename);
|
|
176
|
-
}
|
|
177
|
-
if (options.onConflictMergeFields) {
|
|
178
|
-
options.onConflictMergeFields = options.onConflictMergeFields.map(rename);
|
|
179
|
-
}
|
|
180
|
-
if (options.onConflictExcludeFields) {
|
|
181
|
-
options.onConflictExcludeFields = options.onConflictExcludeFields.map(rename);
|
|
182
|
-
}
|
|
183
|
-
return this.rethrow(this.getConnection('write').updateMany(entityName, where, data, options.ctx, options.upsert, options));
|
|
184
|
-
}
|
|
185
|
-
async nativeUpdateMany(entityName, where, data, options = {}) {
|
|
186
|
-
where = where.map(row => {
|
|
187
|
-
if (Utils.isPlainObject(row)) {
|
|
188
|
-
return this.renameFields(entityName, row, true);
|
|
189
|
-
}
|
|
190
|
-
return row;
|
|
191
|
-
});
|
|
192
|
-
data = data.map(row => {
|
|
193
|
-
this.handleVersionProperty(entityName, row, true);
|
|
194
|
-
return this.renameFields(entityName, row);
|
|
195
|
-
});
|
|
196
|
-
options = { ...options };
|
|
197
|
-
const meta = this.metadata.find(entityName);
|
|
198
|
-
/* v8 ignore next */
|
|
199
|
-
const rename = (field) => meta ? (meta.properties[field]?.fieldNames[0] ?? field) : field;
|
|
200
|
-
if (options.onConflictFields && Array.isArray(options.onConflictFields)) {
|
|
201
|
-
options.onConflictFields = options.onConflictFields.map(rename);
|
|
202
|
-
}
|
|
203
|
-
if (options.onConflictMergeFields) {
|
|
204
|
-
options.onConflictMergeFields = options.onConflictMergeFields.map(rename);
|
|
205
|
-
}
|
|
206
|
-
if (options.onConflictExcludeFields) {
|
|
207
|
-
options.onConflictExcludeFields = options.onConflictExcludeFields.map(rename);
|
|
208
|
-
}
|
|
209
|
-
/* v8 ignore next */
|
|
210
|
-
const pk = meta?.getPrimaryProps()[0].fieldNames[0] ?? '_id';
|
|
211
|
-
const res = await this.rethrow(this.getConnection('write').bulkUpdateMany(entityName, where, data, options.ctx, options.upsert, options));
|
|
212
|
-
if (res.insertedIds) {
|
|
213
|
-
let i = 0;
|
|
214
|
-
res.rows = where.map(cond => {
|
|
215
|
-
if (Utils.isEmpty(cond)) {
|
|
216
|
-
return { [pk]: res.insertedIds[i++] };
|
|
217
|
-
}
|
|
218
|
-
return { [pk]: cond[pk] };
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
return res;
|
|
42
|
+
}
|
|
43
|
+
async find(entityName, where, options = {}) {
|
|
44
|
+
if (this.metadata.find(entityName)?.virtual) {
|
|
45
|
+
return this.findVirtual(entityName, where, options);
|
|
222
46
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
47
|
+
const { first, last, before, after } = options;
|
|
48
|
+
const fields = this.buildFields(entityName, options.populate || [], options.fields, options.exclude);
|
|
49
|
+
where = this.renameFields(entityName, where, true);
|
|
50
|
+
const isCursorPagination = [first, last, before, after].some(v => v != null);
|
|
51
|
+
if (isCursorPagination) {
|
|
52
|
+
const andWhere = (cond1, cond2) => {
|
|
53
|
+
if (Utils.isEmpty(cond1)) {
|
|
54
|
+
return cond2;
|
|
55
|
+
}
|
|
56
|
+
if (Utils.isEmpty(cond2)) {
|
|
57
|
+
return cond1;
|
|
58
|
+
}
|
|
59
|
+
return { $and: [cond1, cond2] };
|
|
60
|
+
};
|
|
61
|
+
const meta = this.metadata.find(entityName);
|
|
62
|
+
const { orderBy: newOrderBy, where: newWhere } = this.processCursorOptions(meta, options, options.orderBy);
|
|
63
|
+
const newWhereConverted = this.renameFields(entityName, newWhere, true);
|
|
64
|
+
const orderBy = Utils.asArray(newOrderBy).map(order => this.renameFields(entityName, order, true));
|
|
65
|
+
const res = await this.rethrow(
|
|
66
|
+
this.getConnection('read').find(entityName, andWhere(where, newWhereConverted), {
|
|
67
|
+
orderBy,
|
|
68
|
+
limit: options.limit,
|
|
69
|
+
offset: options.offset,
|
|
70
|
+
fields,
|
|
71
|
+
ctx: options.ctx,
|
|
72
|
+
loggerContext: options.logging,
|
|
73
|
+
...this.buildQueryOptions(options),
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
if (isCursorPagination && !first && !!last) {
|
|
77
|
+
res.reverse();
|
|
78
|
+
}
|
|
79
|
+
return res.map(r => this.mapResult(r, this.metadata.find(entityName)));
|
|
229
80
|
}
|
|
230
|
-
|
|
231
|
-
|
|
81
|
+
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
82
|
+
const res = await this.rethrow(
|
|
83
|
+
this.getConnection('read').find(entityName, where, {
|
|
84
|
+
orderBy,
|
|
85
|
+
limit: options.limit,
|
|
86
|
+
offset: options.offset,
|
|
87
|
+
fields,
|
|
88
|
+
ctx: options.ctx,
|
|
89
|
+
...this.buildQueryOptions(options),
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
return res.map(r => this.mapResult(r, this.metadata.find(entityName)));
|
|
93
|
+
}
|
|
94
|
+
async findOne(entityName, where, options = { populate: [], orderBy: {} }) {
|
|
95
|
+
if (this.metadata.find(entityName)?.virtual) {
|
|
96
|
+
const [item] = await this.findVirtual(entityName, where, options);
|
|
97
|
+
/* v8 ignore next */
|
|
98
|
+
return item ?? null;
|
|
232
99
|
}
|
|
233
|
-
|
|
234
|
-
|
|
100
|
+
if (Utils.isPrimaryKey(where)) {
|
|
101
|
+
where = this.buildFilterById(entityName, where);
|
|
235
102
|
}
|
|
236
|
-
|
|
237
|
-
|
|
103
|
+
const fields = this.buildFields(entityName, options.populate || [], options.fields, options.exclude);
|
|
104
|
+
where = this.renameFields(entityName, where, true);
|
|
105
|
+
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
106
|
+
const res = await this.rethrow(
|
|
107
|
+
this.getConnection('read').find(entityName, where, {
|
|
108
|
+
orderBy,
|
|
109
|
+
limit: 1,
|
|
110
|
+
fields,
|
|
111
|
+
ctx: options.ctx,
|
|
112
|
+
loggerContext: options.logging,
|
|
113
|
+
...this.buildQueryOptions(options),
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
return this.mapResult(res[0], this.metadata.find(entityName));
|
|
117
|
+
}
|
|
118
|
+
async findVirtual(entityName, where, options) {
|
|
119
|
+
const meta = this.metadata.find(entityName);
|
|
120
|
+
if (meta.expression instanceof Function) {
|
|
121
|
+
const em = this.createEntityManager();
|
|
122
|
+
return meta.expression(em, where, options);
|
|
238
123
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
if (options.maxTimeMS != null) {
|
|
251
|
-
ret.maxTimeMS = options.maxTimeMS;
|
|
252
|
-
}
|
|
253
|
-
if (options.allowDiskUse != null) {
|
|
254
|
-
ret.allowDiskUse = options.allowDiskUse;
|
|
255
|
-
}
|
|
256
|
-
return ret;
|
|
124
|
+
/* v8 ignore next */
|
|
125
|
+
return super.findVirtual(entityName, where, options);
|
|
126
|
+
}
|
|
127
|
+
async *streamVirtual(entityName, where, options) {
|
|
128
|
+
const meta = this.metadata.find(entityName);
|
|
129
|
+
if (meta.expression instanceof Function) {
|
|
130
|
+
const em = this.createEntityManager();
|
|
131
|
+
const stream = await meta.expression(em, where, options, true);
|
|
132
|
+
yield* stream;
|
|
133
|
+
return;
|
|
257
134
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
// copy to new variable to prevent changing the T type or doing as unknown casts
|
|
266
|
-
const copiedData = Object.assign({}, data); // copy first
|
|
267
|
-
const meta = this.metadata.find(entityName);
|
|
268
|
-
if (meta?.serializedPrimaryKey && !meta.embeddable && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
|
|
269
|
-
Utils.renameKey(copiedData, meta.serializedPrimaryKey, meta.primaryKeys[0]);
|
|
270
|
-
}
|
|
271
|
-
if (meta && !meta.embeddable) {
|
|
272
|
-
this.inlineEmbeddables(meta, copiedData, dotPaths);
|
|
273
|
-
}
|
|
274
|
-
// If we had a query with $fulltext and some filter we end up with $and with $fulltext in it.
|
|
275
|
-
// We will try to move $fulltext to top level.
|
|
276
|
-
if (copiedData.$and) {
|
|
277
|
-
for (let i = 0; i < copiedData.$and.length; i++) {
|
|
278
|
-
const and = copiedData.$and[i];
|
|
279
|
-
if ('$fulltext' in and) {
|
|
280
|
-
/* v8 ignore next */
|
|
281
|
-
if ('$fulltext' in copiedData) {
|
|
282
|
-
throw new Error('Cannot merge multiple $fulltext conditions to top level of the query object.');
|
|
283
|
-
}
|
|
284
|
-
copiedData.$fulltext = and.$fulltext;
|
|
285
|
-
delete and.$fulltext;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
// move search terms from data['$fulltext'] to mongo's structure: data['$text']['search']
|
|
290
|
-
if ('$fulltext' in copiedData) {
|
|
291
|
-
copiedData.$text = { $search: copiedData.$fulltext };
|
|
292
|
-
delete copiedData.$fulltext;
|
|
293
|
-
}
|
|
294
|
-
// mongo only allows the $text operator in the root of the object and will
|
|
295
|
-
// search all documents where the field has a text index.
|
|
296
|
-
if (Utils.hasNestedKey(copiedData, '$fulltext')) {
|
|
297
|
-
throw new Error('Full text search is only supported on the top level of the query object.');
|
|
298
|
-
}
|
|
299
|
-
Utils.keys(copiedData).forEach(k => {
|
|
300
|
-
if (Utils.isOperator(k)) {
|
|
301
|
-
if (Array.isArray(copiedData[k])) {
|
|
302
|
-
copiedData[k] = copiedData[k].map(v => this.renameFields(entityName, v, dotPaths, object, false));
|
|
303
|
-
}
|
|
304
|
-
else {
|
|
305
|
-
copiedData[k] = this.renameFields(entityName, copiedData[k], dotPaths, object, false);
|
|
306
|
-
}
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
if (meta?.properties[k]) {
|
|
310
|
-
const prop = meta.properties[k];
|
|
311
|
-
let isObjectId = false;
|
|
312
|
-
if (prop.kind === ReferenceKind.SCALAR) {
|
|
313
|
-
isObjectId = prop.type === 'ObjectId';
|
|
314
|
-
}
|
|
315
|
-
else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
316
|
-
if (copiedData[prop.name] == null) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
if (prop.array && Array.isArray(copiedData[prop.name])) {
|
|
320
|
-
copiedData[prop.name] = copiedData[prop.name].map((item) => this.renameFields(prop.targetMeta.class, item, dotPaths, true, false));
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
copiedData[prop.name] = this.renameFields(prop.targetMeta.class, copiedData[prop.name], dotPaths, prop.object || object, false);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
else if (prop.polymorphic && prop.fieldNames?.length >= 2) {
|
|
327
|
-
// Polymorphic M:1: split into discriminator + FK fields
|
|
328
|
-
const value = copiedData[k];
|
|
329
|
-
delete copiedData[k];
|
|
330
|
-
if (value instanceof PolymorphicRef) {
|
|
331
|
-
copiedData[prop.fieldNames[0]] = value.discriminator;
|
|
332
|
-
const idField = prop.fieldNames[1];
|
|
333
|
-
const targetMeta = this.metadata.find(prop.discriminatorMap[value.discriminator]);
|
|
334
|
-
const hasObjectId = targetMeta && targetMeta.properties[targetMeta.primaryKeys[0]]?.type === 'ObjectId';
|
|
335
|
-
copiedData[idField] = hasObjectId ? this.convertObjectIds(value.id) : value.id;
|
|
336
|
-
}
|
|
337
|
-
else if (Array.isArray(value)) {
|
|
338
|
-
// Tuple format: [discriminator, id]
|
|
339
|
-
copiedData[prop.fieldNames[0]] = value[0];
|
|
340
|
-
copiedData[prop.fieldNames[1]] = value[1] != null ? this.convertObjectIds(value[1]) : value[1];
|
|
341
|
-
}
|
|
342
|
-
else if (value == null) {
|
|
343
|
-
prop.fieldNames.forEach(f => (copiedData[f] = null));
|
|
344
|
-
}
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
const meta2 = this.metadata.find(prop.targetMeta.class);
|
|
349
|
-
const pk = meta2.properties[meta2.primaryKeys[0]];
|
|
350
|
-
isObjectId = pk.type === 'ObjectId';
|
|
351
|
-
}
|
|
352
|
-
if (isObjectId) {
|
|
353
|
-
copiedData[k] = this.convertObjectIds(copiedData[k]);
|
|
354
|
-
}
|
|
355
|
-
if (prop.fieldNames) {
|
|
356
|
-
Utils.renameKey(copiedData, k, prop.fieldNames[0]);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
if (Utils.isPlainObject(copiedData[k]) && '$re' in copiedData[k]) {
|
|
360
|
-
copiedData[k] = new RegExp(copiedData[k].$re);
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
return copiedData;
|
|
364
|
-
}
|
|
365
|
-
convertObjectIds(data) {
|
|
366
|
-
if (data instanceof ObjectId) {
|
|
367
|
-
return data;
|
|
368
|
-
}
|
|
369
|
-
if (typeof data === 'string' && /^[0-9a-f]{24}$/i.exec(data)) {
|
|
370
|
-
return new ObjectId(data);
|
|
371
|
-
}
|
|
372
|
-
if (Array.isArray(data)) {
|
|
373
|
-
return data.map((item) => this.convertObjectIds(item));
|
|
374
|
-
}
|
|
375
|
-
if (Utils.isObject(data)) {
|
|
376
|
-
Object.keys(data).forEach(k => {
|
|
377
|
-
data[k] = this.convertObjectIds(data[k]);
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
return data;
|
|
135
|
+
/* v8 ignore next */
|
|
136
|
+
return super.findVirtual(entityName, where, options);
|
|
137
|
+
}
|
|
138
|
+
async count(entityName, where, options = {}) {
|
|
139
|
+
/* v8 ignore next */
|
|
140
|
+
if (this.metadata.find(entityName)?.virtual) {
|
|
141
|
+
return this.countVirtual(entityName, where, options);
|
|
381
142
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
143
|
+
where = this.renameFields(entityName, where, true);
|
|
144
|
+
const queryOpts = this.buildQueryOptions(options);
|
|
145
|
+
return this.rethrow(
|
|
146
|
+
this.getConnection('read').countDocuments(entityName, where, {
|
|
147
|
+
ctx: options.ctx,
|
|
148
|
+
loggerContext: options.logging,
|
|
149
|
+
...queryOpts,
|
|
150
|
+
}),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
async nativeInsert(entityName, data, options = {}) {
|
|
154
|
+
this.handleVersionProperty(entityName, data);
|
|
155
|
+
data = this.renameFields(entityName, data);
|
|
156
|
+
return this.rethrow(this.getConnection('write').insertOne(entityName, data, options.ctx));
|
|
157
|
+
}
|
|
158
|
+
async nativeInsertMany(entityName, data, options = {}) {
|
|
159
|
+
data = data.map(item => {
|
|
160
|
+
this.handleVersionProperty(entityName, item);
|
|
161
|
+
return this.renameFields(entityName, item);
|
|
162
|
+
});
|
|
163
|
+
const meta = this.metadata.find(entityName);
|
|
164
|
+
/* v8 ignore next */
|
|
165
|
+
const pk = meta?.getPrimaryProps()[0].fieldNames[0] ?? '_id';
|
|
166
|
+
const res = await this.rethrow(this.getConnection('write').insertMany(entityName, data, options.ctx));
|
|
167
|
+
res.rows = res.insertedIds.map(id => ({ [pk]: id }));
|
|
168
|
+
return res;
|
|
169
|
+
}
|
|
170
|
+
async nativeUpdate(entityName, where, data, options = {}) {
|
|
171
|
+
if (Utils.isPrimaryKey(where)) {
|
|
172
|
+
where = this.buildFilterById(entityName, where);
|
|
173
|
+
}
|
|
174
|
+
this.handleVersionProperty(entityName, data, true);
|
|
175
|
+
data = this.renameFields(entityName, data);
|
|
176
|
+
where = this.renameFields(entityName, where, true);
|
|
177
|
+
options = { ...options };
|
|
178
|
+
const meta = this.metadata.find(entityName);
|
|
179
|
+
/* v8 ignore next */
|
|
180
|
+
const rename = field => (meta ? (meta.properties[field]?.fieldNames[0] ?? field) : field);
|
|
181
|
+
if (options.onConflictFields && Array.isArray(options.onConflictFields)) {
|
|
182
|
+
options.onConflictFields = options.onConflictFields.map(rename);
|
|
183
|
+
}
|
|
184
|
+
if (options.onConflictMergeFields) {
|
|
185
|
+
options.onConflictMergeFields = options.onConflictMergeFields.map(rename);
|
|
186
|
+
}
|
|
187
|
+
if (options.onConflictExcludeFields) {
|
|
188
|
+
options.onConflictExcludeFields = options.onConflictExcludeFields.map(rename);
|
|
189
|
+
}
|
|
190
|
+
return this.rethrow(
|
|
191
|
+
this.getConnection('write').updateMany(entityName, where, data, options.ctx, options.upsert, options),
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
async nativeUpdateMany(entityName, where, data, options = {}) {
|
|
195
|
+
where = where.map(row => {
|
|
196
|
+
if (Utils.isPlainObject(row)) {
|
|
197
|
+
return this.renameFields(entityName, row, true);
|
|
198
|
+
}
|
|
199
|
+
return row;
|
|
200
|
+
});
|
|
201
|
+
data = data.map(row => {
|
|
202
|
+
this.handleVersionProperty(entityName, row, true);
|
|
203
|
+
return this.renameFields(entityName, row);
|
|
204
|
+
});
|
|
205
|
+
options = { ...options };
|
|
206
|
+
const meta = this.metadata.find(entityName);
|
|
207
|
+
/* v8 ignore next */
|
|
208
|
+
const rename = field => (meta ? (meta.properties[field]?.fieldNames[0] ?? field) : field);
|
|
209
|
+
if (options.onConflictFields && Array.isArray(options.onConflictFields)) {
|
|
210
|
+
options.onConflictFields = options.onConflictFields.map(rename);
|
|
211
|
+
}
|
|
212
|
+
if (options.onConflictMergeFields) {
|
|
213
|
+
options.onConflictMergeFields = options.onConflictMergeFields.map(rename);
|
|
214
|
+
}
|
|
215
|
+
if (options.onConflictExcludeFields) {
|
|
216
|
+
options.onConflictExcludeFields = options.onConflictExcludeFields.map(rename);
|
|
217
|
+
}
|
|
218
|
+
/* v8 ignore next */
|
|
219
|
+
const pk = meta?.getPrimaryProps()[0].fieldNames[0] ?? '_id';
|
|
220
|
+
const res = await this.rethrow(
|
|
221
|
+
this.getConnection('write').bulkUpdateMany(entityName, where, data, options.ctx, options.upsert, options),
|
|
222
|
+
);
|
|
223
|
+
if (res.insertedIds) {
|
|
224
|
+
let i = 0;
|
|
225
|
+
res.rows = where.map(cond => {
|
|
226
|
+
if (Utils.isEmpty(cond)) {
|
|
227
|
+
return { [pk]: res.insertedIds[i++] };
|
|
228
|
+
}
|
|
229
|
+
return { [pk]: cond[pk] };
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return res;
|
|
233
|
+
}
|
|
234
|
+
async nativeDelete(entityName, where, options = {}) {
|
|
235
|
+
if (Utils.isPrimaryKey(where)) {
|
|
236
|
+
where = this.buildFilterById(entityName, where);
|
|
237
|
+
}
|
|
238
|
+
where = this.renameFields(entityName, where, true);
|
|
239
|
+
return this.rethrow(this.getConnection('write').deleteMany(entityName, where, options.ctx));
|
|
240
|
+
}
|
|
241
|
+
async aggregate(entityName, pipeline, ctx) {
|
|
242
|
+
return this.rethrow(this.getConnection('read').aggregate(entityName, pipeline, ctx));
|
|
243
|
+
}
|
|
244
|
+
async *streamAggregate(entityName, pipeline, ctx) {
|
|
245
|
+
yield* this.getConnection('read').streamAggregate(entityName, pipeline, ctx);
|
|
246
|
+
}
|
|
247
|
+
getPlatform() {
|
|
248
|
+
return this.platform;
|
|
249
|
+
}
|
|
250
|
+
buildQueryOptions(options) {
|
|
251
|
+
if (options.collation != null && typeof options.collation === 'string') {
|
|
252
|
+
throw new Error(
|
|
253
|
+
"Collation option for MongoDB must be a CollationOptions object (e.g. { locale: 'en' }). Use a string only with SQL drivers.",
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
const ret = {};
|
|
257
|
+
if (options.collation) {
|
|
258
|
+
ret.collation = options.collation;
|
|
259
|
+
}
|
|
260
|
+
if (options.indexHint != null) {
|
|
261
|
+
ret.indexHint = options.indexHint;
|
|
426
262
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
263
|
+
if (options.maxTimeMS != null) {
|
|
264
|
+
ret.maxTimeMS = options.maxTimeMS;
|
|
265
|
+
}
|
|
266
|
+
if (options.allowDiskUse != null) {
|
|
267
|
+
ret.allowDiskUse = options.allowDiskUse;
|
|
268
|
+
}
|
|
269
|
+
return ret;
|
|
270
|
+
}
|
|
271
|
+
renameFields(entityName, data, dotPaths = false, object, root = true) {
|
|
272
|
+
if (data == null && root) {
|
|
273
|
+
return {};
|
|
274
|
+
}
|
|
275
|
+
if (typeof data !== 'object' || data === null) {
|
|
276
|
+
return data;
|
|
277
|
+
}
|
|
278
|
+
// copy to new variable to prevent changing the T type or doing as unknown casts
|
|
279
|
+
const copiedData = Object.assign({}, data); // copy first
|
|
280
|
+
const meta = this.metadata.find(entityName);
|
|
281
|
+
if (meta?.serializedPrimaryKey && !meta.embeddable && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
|
|
282
|
+
Utils.renameKey(copiedData, meta.serializedPrimaryKey, meta.primaryKeys[0]);
|
|
283
|
+
}
|
|
284
|
+
if (meta && !meta.embeddable) {
|
|
285
|
+
this.inlineEmbeddables(meta, copiedData, dotPaths);
|
|
286
|
+
}
|
|
287
|
+
// If we had a query with $fulltext and some filter we end up with $and with $fulltext in it.
|
|
288
|
+
// We will try to move $fulltext to top level.
|
|
289
|
+
if (copiedData.$and) {
|
|
290
|
+
for (let i = 0; i < copiedData.$and.length; i++) {
|
|
291
|
+
const and = copiedData.$and[i];
|
|
292
|
+
if ('$fulltext' in and) {
|
|
293
|
+
/* v8 ignore next */
|
|
294
|
+
if ('$fulltext' in copiedData) {
|
|
295
|
+
throw new Error('Cannot merge multiple $fulltext conditions to top level of the query object.');
|
|
296
|
+
}
|
|
297
|
+
copiedData.$fulltext = and.$fulltext;
|
|
298
|
+
delete and.$fulltext;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// move search terms from data['$fulltext'] to mongo's structure: data['$text']['search']
|
|
303
|
+
if ('$fulltext' in copiedData) {
|
|
304
|
+
copiedData.$text = { $search: copiedData.$fulltext };
|
|
305
|
+
delete copiedData.$fulltext;
|
|
306
|
+
}
|
|
307
|
+
// mongo only allows the $text operator in the root of the object and will
|
|
308
|
+
// search all documents where the field has a text index.
|
|
309
|
+
if (Utils.hasNestedKey(copiedData, '$fulltext')) {
|
|
310
|
+
throw new Error('Full text search is only supported on the top level of the query object.');
|
|
311
|
+
}
|
|
312
|
+
Utils.keys(copiedData).forEach(k => {
|
|
313
|
+
if (Utils.isOperator(k)) {
|
|
314
|
+
if (Array.isArray(copiedData[k])) {
|
|
315
|
+
copiedData[k] = copiedData[k].map(v => this.renameFields(entityName, v, dotPaths, object, false));
|
|
316
|
+
} else {
|
|
317
|
+
copiedData[k] = this.renameFields(entityName, copiedData[k], dotPaths, object, false);
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (meta?.properties[k]) {
|
|
322
|
+
const prop = meta.properties[k];
|
|
323
|
+
let isObjectId = false;
|
|
324
|
+
if (prop.kind === ReferenceKind.SCALAR) {
|
|
325
|
+
isObjectId = prop.type === 'ObjectId';
|
|
326
|
+
} else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
327
|
+
if (copiedData[prop.name] == null) {
|
|
430
328
|
return;
|
|
329
|
+
}
|
|
330
|
+
if (prop.array && Array.isArray(copiedData[prop.name])) {
|
|
331
|
+
copiedData[prop.name] = copiedData[prop.name].map(item =>
|
|
332
|
+
this.renameFields(prop.targetMeta.class, item, dotPaths, true, false),
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
copiedData[prop.name] = this.renameFields(
|
|
336
|
+
prop.targetMeta.class,
|
|
337
|
+
copiedData[prop.name],
|
|
338
|
+
dotPaths,
|
|
339
|
+
prop.object || object,
|
|
340
|
+
false,
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
} else if (prop.polymorphic && prop.fieldNames?.length >= 2) {
|
|
344
|
+
// Polymorphic M:1: split into discriminator + FK fields
|
|
345
|
+
const value = copiedData[k];
|
|
346
|
+
delete copiedData[k];
|
|
347
|
+
if (value instanceof PolymorphicRef) {
|
|
348
|
+
copiedData[prop.fieldNames[0]] = value.discriminator;
|
|
349
|
+
const idField = prop.fieldNames[1];
|
|
350
|
+
const targetMeta = this.metadata.find(prop.discriminatorMap[value.discriminator]);
|
|
351
|
+
const hasObjectId = targetMeta && targetMeta.properties[targetMeta.primaryKeys[0]]?.type === 'ObjectId';
|
|
352
|
+
copiedData[idField] = hasObjectId ? this.convertObjectIds(value.id) : value.id;
|
|
353
|
+
} else if (Array.isArray(value)) {
|
|
354
|
+
// Tuple format: [discriminator, id]
|
|
355
|
+
copiedData[prop.fieldNames[0]] = value[0];
|
|
356
|
+
copiedData[prop.fieldNames[1]] = value[1] != null ? this.convertObjectIds(value[1]) : value[1];
|
|
357
|
+
} else if (value == null) {
|
|
358
|
+
prop.fieldNames.forEach(f => (copiedData[f] = null));
|
|
359
|
+
}
|
|
360
|
+
return;
|
|
361
|
+
} else {
|
|
362
|
+
const meta2 = this.metadata.find(prop.targetMeta.class);
|
|
363
|
+
const pk = meta2.properties[meta2.primaryKeys[0]];
|
|
364
|
+
isObjectId = pk.type === 'ObjectId';
|
|
365
|
+
}
|
|
366
|
+
if (isObjectId) {
|
|
367
|
+
copiedData[k] = this.convertObjectIds(copiedData[k]);
|
|
368
|
+
}
|
|
369
|
+
if (prop.fieldNames) {
|
|
370
|
+
Utils.renameKey(copiedData, k, prop.fieldNames[0]);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (Utils.isPlainObject(copiedData[k]) && '$re' in copiedData[k]) {
|
|
374
|
+
copiedData[k] = new RegExp(copiedData[k].$re);
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
return copiedData;
|
|
378
|
+
}
|
|
379
|
+
convertObjectIds(data) {
|
|
380
|
+
if (data instanceof ObjectId) {
|
|
381
|
+
return data;
|
|
382
|
+
}
|
|
383
|
+
if (typeof data === 'string' && /^[0-9a-f]{24}$/i.exec(data)) {
|
|
384
|
+
return new ObjectId(data);
|
|
385
|
+
}
|
|
386
|
+
if (Array.isArray(data)) {
|
|
387
|
+
return data.map(item => this.convertObjectIds(item));
|
|
388
|
+
}
|
|
389
|
+
if (Utils.isObject(data)) {
|
|
390
|
+
Object.keys(data).forEach(k => {
|
|
391
|
+
data[k] = this.convertObjectIds(data[k]);
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
return data;
|
|
395
|
+
}
|
|
396
|
+
buildFilterById(entityName, id) {
|
|
397
|
+
const meta = this.metadata.find(entityName);
|
|
398
|
+
if (meta.properties[meta.primaryKeys[0]].type === 'ObjectId') {
|
|
399
|
+
return { _id: new ObjectId(id) };
|
|
400
|
+
}
|
|
401
|
+
return { _id: id };
|
|
402
|
+
}
|
|
403
|
+
buildFields(entityName, populate, fields, exclude) {
|
|
404
|
+
const meta = this.metadata.get(entityName);
|
|
405
|
+
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => this.isPopulated(meta, prop, p)));
|
|
406
|
+
const ret = [];
|
|
407
|
+
if (fields) {
|
|
408
|
+
for (let field of fields) {
|
|
409
|
+
/* v8 ignore next */
|
|
410
|
+
if (Utils.isPlainObject(field)) {
|
|
411
|
+
continue;
|
|
431
412
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
data[versionProperty.name] ??= new Date();
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
data[versionProperty.name] ??= update ? { $inc: 1 } : 1;
|
|
413
|
+
if (field.toString().includes('.')) {
|
|
414
|
+
field = field.toString().substring(0, field.toString().indexOf('.'));
|
|
438
415
|
}
|
|
416
|
+
let prop = meta.properties[field];
|
|
417
|
+
/* v8 ignore next */
|
|
418
|
+
if (prop) {
|
|
419
|
+
if (!prop.fieldNames) {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
prop = prop.serializedPrimaryKey ? meta.getPrimaryProps()[0] : prop;
|
|
423
|
+
ret.push(prop.fieldNames[0]);
|
|
424
|
+
} else if (field === '*') {
|
|
425
|
+
const props = meta.props.filter(prop => this.platform.shouldHaveColumn(prop, populate));
|
|
426
|
+
ret.push(...Utils.flatten(props.filter(p => !lazyProps.includes(p)).map(p => p.fieldNames)));
|
|
427
|
+
} else {
|
|
428
|
+
ret.push(field);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
ret.unshift(...meta.primaryKeys.filter(pk => !fields.includes(pk)));
|
|
432
|
+
} else if (!Utils.isEmpty(exclude) || lazyProps.some(p => !p.formula)) {
|
|
433
|
+
const props = meta.props.filter(prop => this.platform.shouldHaveColumn(prop, populate, exclude));
|
|
434
|
+
ret.push(...Utils.flatten(props.filter(p => !lazyProps.includes(p)).map(p => p.fieldNames)));
|
|
435
|
+
}
|
|
436
|
+
return ret.length > 0 ? ret : undefined;
|
|
437
|
+
}
|
|
438
|
+
handleVersionProperty(entityName, data, update = false) {
|
|
439
|
+
const meta = this.metadata.find(entityName);
|
|
440
|
+
if (!meta?.versionProperty) {
|
|
441
|
+
return;
|
|
439
442
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
+
const versionProperty = meta.properties[meta.versionProperty];
|
|
444
|
+
if (versionProperty.runtimeType === 'Date') {
|
|
445
|
+
data[versionProperty.name] ??= new Date();
|
|
446
|
+
} else {
|
|
447
|
+
data[versionProperty.name] ??= update ? { $inc: 1 } : 1;
|
|
443
448
|
}
|
|
449
|
+
}
|
|
450
|
+
/** @inheritDoc */
|
|
451
|
+
getORMClass() {
|
|
452
|
+
return MongoMikroORM;
|
|
453
|
+
}
|
|
444
454
|
}
|