c2-mongoose 2.1.229 → 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 +3 -3
- package/dist/flow/SearcherFlow.js +36 -12
- package/package.json +1 -1
- package/src/flow/SearcherFlow.ts +42 -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,12 +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;
|
|
28
27
|
buildOrdenation(): any;
|
|
28
|
+
buildRegex(searchText: string): RegExp;
|
|
29
29
|
}
|
|
30
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,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,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;
|
|
@@ -290,6 +298,22 @@ var SearcherFlow = /** @class */ (function () {
|
|
|
290
298
|
order[this.orderBy] = this.orderSense === "desc" ? -1 : 1;
|
|
291
299
|
return order;
|
|
292
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
|
+
};
|
|
293
317
|
return SearcherFlow;
|
|
294
318
|
}());
|
|
295
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,7 +56,7 @@ 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() })
|
|
@@ -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
|
|
|
@@ -274,7 +286,24 @@ 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
|
+
}
|
|
278
307
|
}
|
|
279
308
|
|
|
280
309
|
export default SearcherFlow
|