@abejarano/ts-mongodb-criteria 1.9.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -182,8 +182,9 @@ Use the `collection` argument inside `ensureIndexes` to avoid recursion.
|
|
|
182
182
|
MongoRepository provides ready-to-use public methods for repositories that extend it:
|
|
183
183
|
|
|
184
184
|
- `list(criteria, fieldsToExclude?)` for paginated queries
|
|
185
|
-
- `
|
|
186
|
-
- `
|
|
185
|
+
- `many(filter, transaction?)` to fetch multiple entities matching a filter
|
|
186
|
+
- `one(filter, transaction?)` to fetch a single entity
|
|
187
|
+
- `upsert(entity, transaction?)` to persist an aggregate
|
|
187
188
|
Internal helpers are private, so repositories should call these public methods
|
|
188
189
|
directly.
|
|
189
190
|
|
|
@@ -214,6 +215,10 @@ await MongoTransaction.run(async (tx) => {
|
|
|
214
215
|
await userRepository.upsert(user, tx)
|
|
215
216
|
await auditRepository.upsert(auditEntry, tx)
|
|
216
217
|
await sessionRepository.delete({ userId: user.getId() }, undefined, tx)
|
|
218
|
+
|
|
219
|
+
// Reads can observe writes made earlier in this transaction.
|
|
220
|
+
const persistedUser = await userRepository.one({ id: user.getId() }, tx)
|
|
221
|
+
const activeUsers = await userRepository.many({ status: "active" }, tx)
|
|
217
222
|
})
|
|
218
223
|
```
|
|
219
224
|
|
|
@@ -232,8 +237,8 @@ async deactivateUser(id: string, tx: MongoTransaction): Promise<void> {
|
|
|
232
237
|
|
|
233
238
|
MongoDB transactions require a replica set or a sharded cluster; standalone
|
|
234
239
|
MongoDB instances do not support them. This initial API applies the transaction
|
|
235
|
-
context
|
|
236
|
-
|
|
240
|
+
context to `upsert`, `delete`, protected `updateOne`, `one`, and `list`.
|
|
241
|
+
Pass `tx` as the third argument to `list` after `fieldsToExclude`, and as the second argument to `many`.
|
|
237
242
|
|
|
238
243
|
**Your First Query in 30 Seconds:**
|
|
239
244
|
|
|
@@ -11,9 +11,12 @@ class MongoRepository {
|
|
|
11
11
|
this.criteriaConverter = new MongoCriteriaConverter_1.MongoCriteriaConverter();
|
|
12
12
|
}
|
|
13
13
|
/** Finds a single entity and hydrates it via the aggregate's fromPrimitives. */
|
|
14
|
-
async one(filter) {
|
|
14
|
+
async one(filter, transaction) {
|
|
15
15
|
const collection = await this.collection();
|
|
16
|
-
const
|
|
16
|
+
const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
|
|
17
|
+
const result = session
|
|
18
|
+
? await collection.findOne(filter, { session })
|
|
19
|
+
: await collection.findOne(filter);
|
|
17
20
|
if (!result) {
|
|
18
21
|
return null;
|
|
19
22
|
}
|
|
@@ -22,14 +25,25 @@ class MongoRepository {
|
|
|
22
25
|
id: result._id.toString(),
|
|
23
26
|
});
|
|
24
27
|
}
|
|
28
|
+
async many(filter, transaction) {
|
|
29
|
+
const collection = await this.collection();
|
|
30
|
+
const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
|
|
31
|
+
const documents = await collection
|
|
32
|
+
.find(filter, session === undefined ? undefined : { session })
|
|
33
|
+
.toArray();
|
|
34
|
+
return documents.map((document) => this.aggregateRootClass.fromPrimitives({
|
|
35
|
+
...document,
|
|
36
|
+
id: document._id.toString(),
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
25
39
|
/** Upserts an aggregate by delegating to persist with its id. */
|
|
26
40
|
async upsert(entity, transaction) {
|
|
27
41
|
await this.persist(entity.getId(), entity, transaction);
|
|
28
42
|
}
|
|
29
43
|
/** Lists entities by criteria and returns a paginated response. */
|
|
30
|
-
async list(criteria, fieldsToExclude = []) {
|
|
31
|
-
const documents = await this.searchByCriteria(criteria, fieldsToExclude);
|
|
32
|
-
return this.paginate(documents);
|
|
44
|
+
async list(criteria, fieldsToExclude = [], transaction) {
|
|
45
|
+
const documents = await this.searchByCriteria(criteria, fieldsToExclude, transaction);
|
|
46
|
+
return this.paginate(documents, transaction);
|
|
33
47
|
}
|
|
34
48
|
/**
|
|
35
49
|
* Deletes documents from the database based on a filter and optional options.
|
|
@@ -80,13 +94,14 @@ class MongoRepository {
|
|
|
80
94
|
},
|
|
81
95
|
}, transaction);
|
|
82
96
|
}
|
|
83
|
-
async searchByCriteria(criteria, fieldsToExclude = []) {
|
|
97
|
+
async searchByCriteria(criteria, fieldsToExclude = [], transaction) {
|
|
84
98
|
this.criteria = criteria;
|
|
85
99
|
this.query = this.criteriaConverter.convert(criteria);
|
|
86
100
|
const collection = await this.collection();
|
|
101
|
+
const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
|
|
87
102
|
if (fieldsToExclude.length === 0) {
|
|
88
103
|
const results = await collection
|
|
89
|
-
.find(this.query.filter, {})
|
|
104
|
+
.find(this.query.filter, session ? { session } : {})
|
|
90
105
|
.sort(this.query.sort)
|
|
91
106
|
.skip(this.query.skip)
|
|
92
107
|
.limit(this.query.limit)
|
|
@@ -98,16 +113,19 @@ class MongoRepository {
|
|
|
98
113
|
projection[field] = 0;
|
|
99
114
|
});
|
|
100
115
|
const results = await collection
|
|
101
|
-
.find(this.query.filter, { projection })
|
|
116
|
+
.find(this.query.filter, session ? { projection, session } : { projection })
|
|
102
117
|
.sort(this.query.sort)
|
|
103
118
|
.skip(this.query.skip)
|
|
104
119
|
.limit(this.query.limit)
|
|
105
120
|
.toArray();
|
|
106
121
|
return results.map(({ _id, ...rest }) => rest);
|
|
107
122
|
}
|
|
108
|
-
async paginate(documents) {
|
|
123
|
+
async paginate(documents, transaction) {
|
|
109
124
|
const collection = await this.collection();
|
|
110
|
-
const
|
|
125
|
+
const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
|
|
126
|
+
const count = session
|
|
127
|
+
? await collection.countDocuments(this.query.filter, { session })
|
|
128
|
+
: await collection.countDocuments(this.query.filter);
|
|
111
129
|
const limit = this.criteria?.limit || 10;
|
|
112
130
|
const currentPage = this.criteria?.currentPage || 1;
|
|
113
131
|
const hasNextPage = currentPage * limit < count;
|
|
@@ -8,9 +8,12 @@ export class MongoRepository {
|
|
|
8
8
|
this.criteriaConverter = new MongoCriteriaConverter();
|
|
9
9
|
}
|
|
10
10
|
/** Finds a single entity and hydrates it via the aggregate's fromPrimitives. */
|
|
11
|
-
async one(filter) {
|
|
11
|
+
async one(filter, transaction) {
|
|
12
12
|
const collection = await this.collection();
|
|
13
|
-
const
|
|
13
|
+
const session = MongoTransaction.sessionFor(transaction);
|
|
14
|
+
const result = session
|
|
15
|
+
? await collection.findOne(filter, { session })
|
|
16
|
+
: await collection.findOne(filter);
|
|
14
17
|
if (!result) {
|
|
15
18
|
return null;
|
|
16
19
|
}
|
|
@@ -19,14 +22,25 @@ export class MongoRepository {
|
|
|
19
22
|
id: result._id.toString(),
|
|
20
23
|
});
|
|
21
24
|
}
|
|
25
|
+
async many(filter, transaction) {
|
|
26
|
+
const collection = await this.collection();
|
|
27
|
+
const session = MongoTransaction.sessionFor(transaction);
|
|
28
|
+
const documents = await collection
|
|
29
|
+
.find(filter, session === undefined ? undefined : { session })
|
|
30
|
+
.toArray();
|
|
31
|
+
return documents.map((document) => this.aggregateRootClass.fromPrimitives({
|
|
32
|
+
...document,
|
|
33
|
+
id: document._id.toString(),
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
22
36
|
/** Upserts an aggregate by delegating to persist with its id. */
|
|
23
37
|
async upsert(entity, transaction) {
|
|
24
38
|
await this.persist(entity.getId(), entity, transaction);
|
|
25
39
|
}
|
|
26
40
|
/** Lists entities by criteria and returns a paginated response. */
|
|
27
|
-
async list(criteria, fieldsToExclude = []) {
|
|
28
|
-
const documents = await this.searchByCriteria(criteria, fieldsToExclude);
|
|
29
|
-
return this.paginate(documents);
|
|
41
|
+
async list(criteria, fieldsToExclude = [], transaction) {
|
|
42
|
+
const documents = await this.searchByCriteria(criteria, fieldsToExclude, transaction);
|
|
43
|
+
return this.paginate(documents, transaction);
|
|
30
44
|
}
|
|
31
45
|
/**
|
|
32
46
|
* Deletes documents from the database based on a filter and optional options.
|
|
@@ -77,13 +91,14 @@ export class MongoRepository {
|
|
|
77
91
|
},
|
|
78
92
|
}, transaction);
|
|
79
93
|
}
|
|
80
|
-
async searchByCriteria(criteria, fieldsToExclude = []) {
|
|
94
|
+
async searchByCriteria(criteria, fieldsToExclude = [], transaction) {
|
|
81
95
|
this.criteria = criteria;
|
|
82
96
|
this.query = this.criteriaConverter.convert(criteria);
|
|
83
97
|
const collection = await this.collection();
|
|
98
|
+
const session = MongoTransaction.sessionFor(transaction);
|
|
84
99
|
if (fieldsToExclude.length === 0) {
|
|
85
100
|
const results = await collection
|
|
86
|
-
.find(this.query.filter, {})
|
|
101
|
+
.find(this.query.filter, session ? { session } : {})
|
|
87
102
|
.sort(this.query.sort)
|
|
88
103
|
.skip(this.query.skip)
|
|
89
104
|
.limit(this.query.limit)
|
|
@@ -95,16 +110,19 @@ export class MongoRepository {
|
|
|
95
110
|
projection[field] = 0;
|
|
96
111
|
});
|
|
97
112
|
const results = await collection
|
|
98
|
-
.find(this.query.filter, { projection })
|
|
113
|
+
.find(this.query.filter, session ? { projection, session } : { projection })
|
|
99
114
|
.sort(this.query.sort)
|
|
100
115
|
.skip(this.query.skip)
|
|
101
116
|
.limit(this.query.limit)
|
|
102
117
|
.toArray();
|
|
103
118
|
return results.map(({ _id, ...rest }) => rest);
|
|
104
119
|
}
|
|
105
|
-
async paginate(documents) {
|
|
120
|
+
async paginate(documents, transaction) {
|
|
106
121
|
const collection = await this.collection();
|
|
107
|
-
const
|
|
122
|
+
const session = MongoTransaction.sessionFor(transaction);
|
|
123
|
+
const count = session
|
|
124
|
+
? await collection.countDocuments(this.query.filter, { session })
|
|
125
|
+
: await collection.countDocuments(this.query.filter);
|
|
108
126
|
const limit = this.criteria?.limit || 10;
|
|
109
127
|
const currentPage = this.criteria?.currentPage || 1;
|
|
110
128
|
const hasNextPage = currentPage * limit < count;
|
|
@@ -3,8 +3,9 @@ import { AggregateRoot } from "../AggregateRoot";
|
|
|
3
3
|
import { DeleteOptions } from "mongodb";
|
|
4
4
|
import { MongoTransaction } from "./MongoTransaction";
|
|
5
5
|
export interface IRepository<T extends AggregateRoot> {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
many(filter: object, transaction?: MongoTransaction): Promise<T[]>;
|
|
7
|
+
one(filter: object, transaction?: MongoTransaction): Promise<T | null>;
|
|
8
|
+
list<D>(criteria: Criteria, fieldsToExclude?: string[], transaction?: MongoTransaction): Promise<Paginate<D>>;
|
|
8
9
|
upsert(entity: T, transaction?: MongoTransaction): Promise<void>;
|
|
9
10
|
delete(filter: object, options?: DeleteOptions, transaction?: MongoTransaction): Promise<void>;
|
|
10
11
|
}
|
|
@@ -11,11 +11,12 @@ export declare abstract class MongoRepository<T extends AggregateRoot> {
|
|
|
11
11
|
protected constructor(aggregateRootClass: AggregateRootClass<T>);
|
|
12
12
|
abstract collectionName(): string;
|
|
13
13
|
/** Finds a single entity and hydrates it via the aggregate's fromPrimitives. */
|
|
14
|
-
one(filter: object): Promise<T | null>;
|
|
14
|
+
one(filter: object, transaction?: MongoTransaction): Promise<T | null>;
|
|
15
|
+
many(filter: object, transaction?: MongoTransaction): Promise<T[]>;
|
|
15
16
|
/** Upserts an aggregate by delegating to persist with its id. */
|
|
16
17
|
upsert(entity: T, transaction?: MongoTransaction): Promise<void>;
|
|
17
18
|
/** Lists entities by criteria and returns a paginated response. */
|
|
18
|
-
list<D>(criteria: Criteria, fieldsToExclude?: string[]): Promise<Paginate<D>>;
|
|
19
|
+
list<D>(criteria: Criteria, fieldsToExclude?: string[], transaction?: MongoTransaction): Promise<Paginate<D>>;
|
|
19
20
|
/**
|
|
20
21
|
* Deletes documents from the database based on a filter and optional options.
|
|
21
22
|
*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abejarano/ts-mongodb-criteria",
|
|
3
3
|
"author": "angel bejarano / angel.bejarano@jaspesoft.com",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.11.0",
|
|
5
5
|
"description": "Patrón Criteria para consultas MongoDB en TypeScript",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
7
7
|
"module": "dist/esm/index.js",
|