c2-mongoose 2.1.229 → 2.1.231
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/dist/flow/SearcherFlow.d.ts +4 -3
- package/dist/flow/SearcherFlow.js +51 -12
- package/package.json +1 -1
- package/src/flow/SearcherFlow.ts +59 -14
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import mongoose from "mongoose";
|
|
2
2
|
import { SearchOptions, SearchResponse } from "../types/SearchResponse";
|
|
3
|
-
import SearchFlow from "./SearchFlow";
|
|
4
3
|
export interface IPopulate {
|
|
5
4
|
[key: string]: any;
|
|
6
5
|
path: string;
|
|
@@ -19,12 +18,14 @@ declare class SearcherFlow<D> {
|
|
|
19
18
|
private select;
|
|
20
19
|
private populate;
|
|
21
20
|
private filters;
|
|
22
|
-
constructor(repository: mongoose.Model<any
|
|
21
|
+
constructor(repository: mongoose.Model<any>);
|
|
23
22
|
prepareSearch(search: any): void;
|
|
24
|
-
search(
|
|
23
|
+
search(options: SearchOptions): Promise<SearchResponse<D>>;
|
|
25
24
|
transformObject(originalObject: any): any;
|
|
26
25
|
buildDefaultFilters(objectSearch: any): any;
|
|
27
26
|
isValidObjectId(value: string): boolean;
|
|
28
27
|
buildOrdenation(): any;
|
|
28
|
+
buildRegex(searchText: string): RegExp;
|
|
29
|
+
private reset;
|
|
29
30
|
}
|
|
30
31
|
export default SearcherFlow;
|
|
@@ -56,7 +56,7 @@ var Utils_1 = require("../utils/Utils");
|
|
|
56
56
|
var BuildPopulateSingleFlowItem_1 = __importDefault(require("./item/BuildPopulateSingleFlowItem"));
|
|
57
57
|
var BuildSelectSingleFlowItem_1 = __importDefault(require("./item/BuildSelectSingleFlowItem"));
|
|
58
58
|
var SearcherFlow = /** @class */ (function () {
|
|
59
|
-
function SearcherFlow(repository
|
|
59
|
+
function SearcherFlow(repository) {
|
|
60
60
|
this.searchText = "";
|
|
61
61
|
this.orderSense = "desc";
|
|
62
62
|
this.orderBy = "_id";
|
|
@@ -67,9 +67,6 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
67
67
|
this.populate = [""];
|
|
68
68
|
this.filters = undefined;
|
|
69
69
|
this.model = repository;
|
|
70
|
-
for (var key in search) {
|
|
71
|
-
this[key] = search[key];
|
|
72
|
-
}
|
|
73
70
|
}
|
|
74
71
|
SearcherFlow.prototype.prepareSearch = function (search) {
|
|
75
72
|
for (var key in search) {
|
|
@@ -78,17 +75,13 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
78
75
|
this.filters = this.buildDefaultFilters(this);
|
|
79
76
|
this.page = Number(this.page);
|
|
80
77
|
this.limit = Number(this.limit);
|
|
81
|
-
// this.projection = this.buildProjections()
|
|
82
|
-
// this.populate = this.buildPopulate()
|
|
83
|
-
// this.buildOrdenation()
|
|
84
78
|
};
|
|
85
|
-
SearcherFlow.prototype.search = function (
|
|
79
|
+
SearcherFlow.prototype.search = function (options) {
|
|
86
80
|
return __awaiter(this, void 0, void 0, function () {
|
|
87
81
|
var stagesItems, stagesPaging, stagesMetadata, facet, _i, stagesMetadata_1, metadata, result, _a, resultAux;
|
|
88
82
|
return __generator(this, function (_b) {
|
|
89
83
|
switch (_b.label) {
|
|
90
84
|
case 0:
|
|
91
|
-
console.log("new searcher");
|
|
92
85
|
stagesItems = [];
|
|
93
86
|
if ((0, Utils_1.isNotEmpty)(options.pipelines)) {
|
|
94
87
|
stagesItems.push.apply(stagesItems, options.pipelines);
|
|
@@ -98,7 +91,7 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
98
91
|
}
|
|
99
92
|
stagesItems.push({ $match: this.filters });
|
|
100
93
|
if ((0, Utils_1.isNotEmpty)(this.select)) {
|
|
101
|
-
stagesItems.push({ $project: BuildSelectSingleFlowItem_1.default.build(model, this.select) });
|
|
94
|
+
stagesItems.push({ $project: BuildSelectSingleFlowItem_1.default.build(this.model, this.select) });
|
|
102
95
|
}
|
|
103
96
|
stagesItems.push({ $sort: this.buildOrdenation() });
|
|
104
97
|
if (this.pageable === true) {
|
|
@@ -142,7 +135,7 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
142
135
|
metadata = stagesMetadata_1[_i];
|
|
143
136
|
facet[metadata.id] = metadata.conditions;
|
|
144
137
|
}
|
|
145
|
-
return [4 /*yield*/, model.aggregate([
|
|
138
|
+
return [4 /*yield*/, this.model.aggregate([
|
|
146
139
|
{
|
|
147
140
|
$facet: facet
|
|
148
141
|
},
|
|
@@ -156,12 +149,13 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
156
149
|
result = _b.sent();
|
|
157
150
|
if (!(0, Utils_1.isNotEmpty)(this.populate)) return [3 /*break*/, 3];
|
|
158
151
|
_a = result[0];
|
|
159
|
-
return [4 /*yield*/, model.populate(result[0].items, BuildPopulateSingleFlowItem_1.default.buildPopulate(model, this.populate, this.select))];
|
|
152
|
+
return [4 /*yield*/, this.model.populate(result[0].items, BuildPopulateSingleFlowItem_1.default.buildPopulate(this.model, this.populate, this.select))];
|
|
160
153
|
case 2:
|
|
161
154
|
_a.items = _b.sent();
|
|
162
155
|
_b.label = 3;
|
|
163
156
|
case 3:
|
|
164
157
|
resultAux = this.transformObject(result[0]);
|
|
158
|
+
this.reset();
|
|
165
159
|
return [2 /*return*/, resultAux];
|
|
166
160
|
}
|
|
167
161
|
});
|
|
@@ -187,6 +181,10 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
187
181
|
};
|
|
188
182
|
SearcherFlow.prototype.buildDefaultFilters = function (objectSearch) {
|
|
189
183
|
var _this = this;
|
|
184
|
+
// Recuperar todos os campos do tipo String
|
|
185
|
+
var camposString = Object.keys(this.model.schema.paths).filter(function (campo) {
|
|
186
|
+
return _this.model.schema.paths[campo].instance === 'String';
|
|
187
|
+
});
|
|
190
188
|
var filters = { $and: [] };
|
|
191
189
|
Object.entries(objectSearch).forEach(function (_a) {
|
|
192
190
|
var key = _a[0], value = _a[1];
|
|
@@ -276,6 +274,17 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
276
274
|
}
|
|
277
275
|
}
|
|
278
276
|
});
|
|
277
|
+
if ((0, Utils_1.isNotEmpty)(this.searchText) && (0, Utils_1.isNotEmpty)(camposString)) {
|
|
278
|
+
var regex = this.buildRegex(this.searchText);
|
|
279
|
+
var conditions = { $or: [] };
|
|
280
|
+
for (var _i = 0, camposString_1 = camposString; _i < camposString_1.length; _i++) {
|
|
281
|
+
var fieldString = camposString_1[_i];
|
|
282
|
+
var conditionAux = {};
|
|
283
|
+
conditionAux[fieldString] = { $regex: regex };
|
|
284
|
+
conditions.$or.push(conditionAux);
|
|
285
|
+
}
|
|
286
|
+
filters.$and.push(conditions);
|
|
287
|
+
}
|
|
279
288
|
if (filters.$and.length === 0)
|
|
280
289
|
delete filters['$and'];
|
|
281
290
|
return filters;
|
|
@@ -290,6 +299,36 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
290
299
|
order[this.orderBy] = this.orderSense === "desc" ? -1 : 1;
|
|
291
300
|
return order;
|
|
292
301
|
};
|
|
302
|
+
SearcherFlow.prototype.buildRegex = function (searchText) {
|
|
303
|
+
var regexExpression = searchText
|
|
304
|
+
.replace(/[+?^${}()|[\]\\]/g, '\\$&') //Tratar os caracteres que podem ser chaves, escape os demais q podem ser regex
|
|
305
|
+
.replace(/^"/, '^').replace(/"$/, '$') //Replace aspas duplas para busca exata
|
|
306
|
+
.replace(/^%22/, '^').replace(/%22$/, '$') //Replace aspas duplas para busca exata
|
|
307
|
+
.replace(/%20/, ' ') //Replace espaço em branco para nao quebrar o proximo replace
|
|
308
|
+
.replace(/\*/g, '.*?') //Replace % para o padrão regex (% é muito utilizado como o .*? e é mais simples para o usuario digitar)
|
|
309
|
+
.replace(/%/g, '.*?') //Replace % para o padrão regex (% é muito utilizado como o .*? e é mais simples para o usuario digitar)
|
|
310
|
+
.replace(/[ç|Ç|c|C]/g, '[c,C,ç,Ç]')
|
|
311
|
+
.replace(/[a|á|à|ä|â|A|Á|Â|Ã|Ä]/g, '[a,á,à,ä,â,A,Á,Â,Ã,Ä]')
|
|
312
|
+
.replace(/[e|é|ë|è|E|É|Ë|È]/g, '[e,é,ë,è,E,É,Ë,È]')
|
|
313
|
+
.replace(/[i|í|ï|ì|I|Í|Ï|Ì]/g, '[i,í,ï,ì,I,Í,Ï,Ì]')
|
|
314
|
+
.replace(/[o|ó|ö|ò|õ|O|Ó|Ö|Ô|Õ]/g, '[o,ó,ö,ò,õ,O,Ó,Ö,Ô,Õ]')
|
|
315
|
+
.replace(/[u|ü|ú|ù|U|Ú|Ü|Ù]/g, '[u,ü,ú,ù,U,Ú,Ü,Ù]');
|
|
316
|
+
return new RegExp("".concat(regexExpression), 'i');
|
|
317
|
+
};
|
|
318
|
+
SearcherFlow.prototype.reset = function () {
|
|
319
|
+
for (var key in this) {
|
|
320
|
+
delete this[key];
|
|
321
|
+
}
|
|
322
|
+
this.searchText = "";
|
|
323
|
+
this.orderSense = "desc";
|
|
324
|
+
this.orderBy = "_id";
|
|
325
|
+
this.page = 1;
|
|
326
|
+
this.limit = 50;
|
|
327
|
+
this.pageable = true;
|
|
328
|
+
this.select = [""];
|
|
329
|
+
this.populate = [""];
|
|
330
|
+
this.filters = undefined;
|
|
331
|
+
};
|
|
293
332
|
return SearcherFlow;
|
|
294
333
|
}());
|
|
295
334
|
exports.default = SearcherFlow;
|
package/package.json
CHANGED
package/src/flow/SearcherFlow.ts
CHANGED
|
@@ -2,7 +2,6 @@ import moment from "moment"
|
|
|
2
2
|
import mongoose, { ClientSession, Types } from "mongoose"
|
|
3
3
|
import { SearchOptions, SearchResponse } from "../types/SearchResponse"
|
|
4
4
|
import { isNotEmpty } from "../utils/Utils"
|
|
5
|
-
import SearchFlow from "./SearchFlow"
|
|
6
5
|
import BuildPopulateSingleFlowItem from "./item/BuildPopulateSingleFlowItem"
|
|
7
6
|
import BuildSelectSingleFlowItem from "./item/BuildSelectSingleFlowItem"
|
|
8
7
|
export interface IPopulate {
|
|
@@ -28,11 +27,8 @@ class SearcherFlow<D> {
|
|
|
28
27
|
private populate: string[] = [""]
|
|
29
28
|
private filters: any = undefined
|
|
30
29
|
|
|
31
|
-
constructor(repository: mongoose.Model<any
|
|
30
|
+
constructor(repository: mongoose.Model<any>) {
|
|
32
31
|
this.model = repository
|
|
33
|
-
for (const key in search) {
|
|
34
|
-
this[key] = search[key];
|
|
35
|
-
}
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
public prepareSearch(search: any) {
|
|
@@ -43,14 +39,10 @@ class SearcherFlow<D> {
|
|
|
43
39
|
this.filters = this.buildDefaultFilters(this)
|
|
44
40
|
this.page = Number(this.page)
|
|
45
41
|
this.limit = Number(this.limit)
|
|
46
|
-
// this.projection = this.buildProjections()
|
|
47
|
-
// this.populate = this.buildPopulate()
|
|
48
|
-
// this.buildOrdenation()
|
|
49
42
|
}
|
|
50
43
|
|
|
51
|
-
async search(
|
|
44
|
+
async search(options: SearchOptions): Promise<SearchResponse<D>> {
|
|
52
45
|
|
|
53
|
-
console.log("new searcher")
|
|
54
46
|
let stagesItems: any[] = []
|
|
55
47
|
|
|
56
48
|
if (isNotEmpty(options.pipelines)) {
|
|
@@ -63,7 +55,7 @@ class SearcherFlow<D> {
|
|
|
63
55
|
stagesItems.push({ $match: this.filters })
|
|
64
56
|
|
|
65
57
|
if (isNotEmpty(this.select)) {
|
|
66
|
-
stagesItems.push({ $project: BuildSelectSingleFlowItem.build(model, this.select) })
|
|
58
|
+
stagesItems.push({ $project: BuildSelectSingleFlowItem.build(this.model, this.select) })
|
|
67
59
|
}
|
|
68
60
|
|
|
69
61
|
stagesItems.push({ $sort: this.buildOrdenation() })
|
|
@@ -114,7 +106,7 @@ class SearcherFlow<D> {
|
|
|
114
106
|
facet[metadata.id] = metadata.conditions
|
|
115
107
|
}
|
|
116
108
|
|
|
117
|
-
const result = await model.aggregate(
|
|
109
|
+
const result = await this.model.aggregate(
|
|
118
110
|
[
|
|
119
111
|
{
|
|
120
112
|
$facet: facet
|
|
@@ -128,10 +120,11 @@ class SearcherFlow<D> {
|
|
|
128
120
|
|
|
129
121
|
|
|
130
122
|
if (isNotEmpty(this.populate)) {
|
|
131
|
-
result[0].items = await model.populate(result[0].items, BuildPopulateSingleFlowItem.buildPopulate(model, this.populate, this.select))
|
|
123
|
+
result[0].items = await this.model.populate(result[0].items, BuildPopulateSingleFlowItem.buildPopulate(this.model, this.populate, this.select))
|
|
132
124
|
}
|
|
133
125
|
|
|
134
126
|
let resultAux = this.transformObject(result[0])
|
|
127
|
+
this.reset()
|
|
135
128
|
return resultAux
|
|
136
129
|
}
|
|
137
130
|
|
|
@@ -161,6 +154,13 @@ class SearcherFlow<D> {
|
|
|
161
154
|
}
|
|
162
155
|
|
|
163
156
|
public buildDefaultFilters(objectSearch: any) {
|
|
157
|
+
|
|
158
|
+
// Recuperar todos os campos do tipo String
|
|
159
|
+
const camposString = Object.keys(this.model.schema.paths).filter((campo: string) => {
|
|
160
|
+
return this.model.schema.paths[campo].instance === 'String';
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
|
|
164
164
|
let filters = { $and: [] } as any
|
|
165
165
|
Object.entries(objectSearch).forEach(([key, value]) => {
|
|
166
166
|
if (isNotEmpty(value)) {
|
|
@@ -258,6 +258,18 @@ class SearcherFlow<D> {
|
|
|
258
258
|
}
|
|
259
259
|
})
|
|
260
260
|
|
|
261
|
+
if (isNotEmpty(this.searchText) && isNotEmpty(camposString)) {
|
|
262
|
+
let regex = this.buildRegex(this.searchText)
|
|
263
|
+
let conditions = { $or: [] as any }
|
|
264
|
+
for (let fieldString of camposString) {
|
|
265
|
+
let conditionAux: { [key: string]: any } = {}
|
|
266
|
+
conditionAux[fieldString] = { $regex: regex }
|
|
267
|
+
|
|
268
|
+
conditions.$or.push(conditionAux)
|
|
269
|
+
}
|
|
270
|
+
filters.$and.push(conditions)
|
|
271
|
+
}
|
|
272
|
+
|
|
261
273
|
if (filters.$and.length === 0)
|
|
262
274
|
delete filters['$and']
|
|
263
275
|
|
|
@@ -274,7 +286,40 @@ class SearcherFlow<D> {
|
|
|
274
286
|
this.orderBy = this.orderBy
|
|
275
287
|
order[this.orderBy] = this.orderSense === "desc" ? -1 : 1
|
|
276
288
|
return order
|
|
277
|
-
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
buildRegex(searchText: string): RegExp {
|
|
292
|
+
let regexExpression = searchText
|
|
293
|
+
.replace(/[+?^${}()|[\]\\]/g, '\\$&') //Tratar os caracteres que podem ser chaves, escape os demais q podem ser regex
|
|
294
|
+
.replace(/^"/, '^').replace(/"$/, '$') //Replace aspas duplas para busca exata
|
|
295
|
+
.replace(/^%22/, '^').replace(/%22$/, '$') //Replace aspas duplas para busca exata
|
|
296
|
+
.replace(/%20/, ' ') //Replace espaço em branco para nao quebrar o proximo replace
|
|
297
|
+
.replace(/\*/g, '.*?') //Replace % para o padrão regex (% é muito utilizado como o .*? e é mais simples para o usuario digitar)
|
|
298
|
+
.replace(/%/g, '.*?') //Replace % para o padrão regex (% é muito utilizado como o .*? e é mais simples para o usuario digitar)
|
|
299
|
+
.replace(/[ç|Ç|c|C]/g, '[c,C,ç,Ç]')
|
|
300
|
+
.replace(/[a|á|à|ä|â|A|Á|Â|Ã|Ä]/g, '[a,á,à,ä,â,A,Á,Â,Ã,Ä]')
|
|
301
|
+
.replace(/[e|é|ë|è|E|É|Ë|È]/g, '[e,é,ë,è,E,É,Ë,È]')
|
|
302
|
+
.replace(/[i|í|ï|ì|I|Í|Ï|Ì]/g, '[i,í,ï,ì,I,Í,Ï,Ì]')
|
|
303
|
+
.replace(/[o|ó|ö|ò|õ|O|Ó|Ö|Ô|Õ]/g, '[o,ó,ö,ò,õ,O,Ó,Ö,Ô,Õ]')
|
|
304
|
+
.replace(/[u|ü|ú|ù|U|Ú|Ü|Ù]/g, '[u,ü,ú,ù,U,Ú,Ü,Ù]')
|
|
305
|
+
return new RegExp(`${regexExpression}`, 'i');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private reset() {
|
|
309
|
+
for (const key in this) {
|
|
310
|
+
delete this[key];
|
|
311
|
+
}
|
|
312
|
+
this.searchText = ""
|
|
313
|
+
this.orderSense = "desc"
|
|
314
|
+
this.orderBy = "_id"
|
|
315
|
+
this.page = 1
|
|
316
|
+
this.limit = 50
|
|
317
|
+
this.pageable = true
|
|
318
|
+
|
|
319
|
+
this.select = [""]
|
|
320
|
+
this.populate = [""]
|
|
321
|
+
this.filters = undefined
|
|
322
|
+
}
|
|
278
323
|
}
|
|
279
324
|
|
|
280
325
|
export default SearcherFlow
|