c2-mongoose 2.1.228 → 2.1.230
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 +43 -13
- package/package.json +1 -1
- package/src/flow/SearcherFlow.ts +49 -13
|
@@ -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,11 +18,13 @@ 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;
|
|
27
|
+
buildOrdenation(): any;
|
|
28
|
+
buildRegex(searchText: string): RegExp;
|
|
28
29
|
}
|
|
29
30
|
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,9 +91,9 @@ 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) {
|
|
105
98
|
stagesItems.push({ $skip: ((this.page - 1) * this.limit) || 0 });
|
|
106
99
|
stagesItems.push({ $limit: this.limit });
|
|
@@ -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,7 +149,7 @@ 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;
|
|
@@ -187,6 +180,10 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
187
180
|
};
|
|
188
181
|
SearcherFlow.prototype.buildDefaultFilters = function (objectSearch) {
|
|
189
182
|
var _this = this;
|
|
183
|
+
// Recuperar todos os campos do tipo String
|
|
184
|
+
var camposString = Object.keys(this.model.schema.paths).filter(function (campo) {
|
|
185
|
+
return _this.model.schema.paths[campo].instance === 'String';
|
|
186
|
+
});
|
|
190
187
|
var filters = { $and: [] };
|
|
191
188
|
Object.entries(objectSearch).forEach(function (_a) {
|
|
192
189
|
var key = _a[0], value = _a[1];
|
|
@@ -276,6 +273,17 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
276
273
|
}
|
|
277
274
|
}
|
|
278
275
|
});
|
|
276
|
+
if ((0, Utils_1.isNotEmpty)(this.searchText) && (0, Utils_1.isNotEmpty)(camposString)) {
|
|
277
|
+
var regex = this.buildRegex(this.searchText);
|
|
278
|
+
var conditions = { $or: [] };
|
|
279
|
+
for (var _i = 0, camposString_1 = camposString; _i < camposString_1.length; _i++) {
|
|
280
|
+
var fieldString = camposString_1[_i];
|
|
281
|
+
var conditionAux = {};
|
|
282
|
+
conditionAux[fieldString] = { $regex: regex };
|
|
283
|
+
conditions.$or.push(conditionAux);
|
|
284
|
+
}
|
|
285
|
+
filters.$and.push(conditions);
|
|
286
|
+
}
|
|
279
287
|
if (filters.$and.length === 0)
|
|
280
288
|
delete filters['$and'];
|
|
281
289
|
return filters;
|
|
@@ -284,6 +292,28 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
284
292
|
var objectIdPattern = /^[0-9a-fA-F]{24}$/;
|
|
285
293
|
return objectIdPattern.test(value);
|
|
286
294
|
};
|
|
295
|
+
SearcherFlow.prototype.buildOrdenation = function () {
|
|
296
|
+
var order = {};
|
|
297
|
+
this.orderBy = this.orderBy;
|
|
298
|
+
order[this.orderBy] = this.orderSense === "desc" ? -1 : 1;
|
|
299
|
+
return order;
|
|
300
|
+
};
|
|
301
|
+
SearcherFlow.prototype.buildRegex = function (searchText) {
|
|
302
|
+
var regexExpression = searchText
|
|
303
|
+
.replace(/[+?^${}()|[\]\\]/g, '\\$&') //Tratar os caracteres que podem ser chaves, escape os demais q podem ser regex
|
|
304
|
+
.replace(/^"/, '^').replace(/"$/, '$') //Replace aspas duplas para busca exata
|
|
305
|
+
.replace(/^%22/, '^').replace(/%22$/, '$') //Replace aspas duplas para busca exata
|
|
306
|
+
.replace(/%20/, ' ') //Replace espaço em branco para nao quebrar o proximo replace
|
|
307
|
+
.replace(/\*/g, '.*?') //Replace % para o padrão regex (% é muito utilizado como o .*? e é mais simples para o usuario digitar)
|
|
308
|
+
.replace(/%/g, '.*?') //Replace % para o padrão regex (% é muito utilizado como o .*? e é mais simples para o usuario digitar)
|
|
309
|
+
.replace(/[ç|Ç|c|C]/g, '[c,C,ç,Ç]')
|
|
310
|
+
.replace(/[a|á|à|ä|â|A|Á|Â|Ã|Ä]/g, '[a,á,à,ä,â,A,Á,Â,Ã,Ä]')
|
|
311
|
+
.replace(/[e|é|ë|è|E|É|Ë|È]/g, '[e,é,ë,è,E,É,Ë,È]')
|
|
312
|
+
.replace(/[i|í|ï|ì|I|Í|Ï|Ì]/g, '[i,í,ï,ì,I,Í,Ï,Ì]')
|
|
313
|
+
.replace(/[o|ó|ö|ò|õ|O|Ó|Ö|Ô|Õ]/g, '[o,ó,ö,ò,õ,O,Ó,Ö,Ô,Õ]')
|
|
314
|
+
.replace(/[u|ü|ú|ù|U|Ú|Ü|Ù]/g, '[u,ü,ú,ù,U,Ú,Ü,Ù]');
|
|
315
|
+
return new RegExp("".concat(regexExpression), 'i');
|
|
316
|
+
};
|
|
287
317
|
return SearcherFlow;
|
|
288
318
|
}());
|
|
289
319
|
exports.default = SearcherFlow;
|
package/package.json
CHANGED
package/src/flow/SearcherFlow.ts
CHANGED
|
@@ -28,11 +28,8 @@ class SearcherFlow<D> {
|
|
|
28
28
|
private populate: string[] = [""]
|
|
29
29
|
private filters: any = undefined
|
|
30
30
|
|
|
31
|
-
constructor(repository: mongoose.Model<any
|
|
31
|
+
constructor(repository: mongoose.Model<any>) {
|
|
32
32
|
this.model = repository
|
|
33
|
-
for (const key in search) {
|
|
34
|
-
this[key] = search[key];
|
|
35
|
-
}
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
public prepareSearch(search: any) {
|
|
@@ -43,14 +40,10 @@ class SearcherFlow<D> {
|
|
|
43
40
|
this.filters = this.buildDefaultFilters(this)
|
|
44
41
|
this.page = Number(this.page)
|
|
45
42
|
this.limit = Number(this.limit)
|
|
46
|
-
// this.projection = this.buildProjections()
|
|
47
|
-
// this.populate = this.buildPopulate()
|
|
48
|
-
// this.buildOrdenation()
|
|
49
43
|
}
|
|
50
44
|
|
|
51
|
-
async search(
|
|
45
|
+
async search(options: SearchOptions): Promise<SearchResponse<D>> {
|
|
52
46
|
|
|
53
|
-
console.log("new searcher")
|
|
54
47
|
let stagesItems: any[] = []
|
|
55
48
|
|
|
56
49
|
if (isNotEmpty(options.pipelines)) {
|
|
@@ -63,10 +56,10 @@ class SearcherFlow<D> {
|
|
|
63
56
|
stagesItems.push({ $match: this.filters })
|
|
64
57
|
|
|
65
58
|
if (isNotEmpty(this.select)) {
|
|
66
|
-
stagesItems.push({ $project: BuildSelectSingleFlowItem.build(model, this.select) })
|
|
59
|
+
stagesItems.push({ $project: BuildSelectSingleFlowItem.build(this.model, this.select) })
|
|
67
60
|
}
|
|
68
61
|
|
|
69
|
-
|
|
62
|
+
stagesItems.push({ $sort: this.buildOrdenation() })
|
|
70
63
|
if (this.pageable === true) {
|
|
71
64
|
stagesItems.push({ $skip: ((this.page - 1) * this.limit) || 0 })
|
|
72
65
|
stagesItems.push({ $limit: this.limit })
|
|
@@ -114,7 +107,7 @@ class SearcherFlow<D> {
|
|
|
114
107
|
facet[metadata.id] = metadata.conditions
|
|
115
108
|
}
|
|
116
109
|
|
|
117
|
-
const result = await model.aggregate(
|
|
110
|
+
const result = await this.model.aggregate(
|
|
118
111
|
[
|
|
119
112
|
{
|
|
120
113
|
$facet: facet
|
|
@@ -128,7 +121,7 @@ class SearcherFlow<D> {
|
|
|
128
121
|
|
|
129
122
|
|
|
130
123
|
if (isNotEmpty(this.populate)) {
|
|
131
|
-
result[0].items = await model.populate(result[0].items, BuildPopulateSingleFlowItem.buildPopulate(model, this.populate, this.select))
|
|
124
|
+
result[0].items = await this.model.populate(result[0].items, BuildPopulateSingleFlowItem.buildPopulate(this.model, this.populate, this.select))
|
|
132
125
|
}
|
|
133
126
|
|
|
134
127
|
let resultAux = this.transformObject(result[0])
|
|
@@ -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
|
|
|
@@ -268,6 +280,30 @@ class SearcherFlow<D> {
|
|
|
268
280
|
const objectIdPattern = /^[0-9a-fA-F]{24}$/;
|
|
269
281
|
return objectIdPattern.test(value);
|
|
270
282
|
}
|
|
283
|
+
|
|
284
|
+
public buildOrdenation() {
|
|
285
|
+
let order = {} as any
|
|
286
|
+
this.orderBy = this.orderBy
|
|
287
|
+
order[this.orderBy] = this.orderSense === "desc" ? -1 : 1
|
|
288
|
+
return order
|
|
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
|
+
}
|
|
271
307
|
}
|
|
272
308
|
|
|
273
309
|
export default SearcherFlow
|