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.
@@ -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>, search?: SearchFlow);
21
+ constructor(repository: mongoose.Model<any>);
23
22
  prepareSearch(search: any): void;
24
- search(model: mongoose.Model<any>, options: SearchOptions): Promise<SearchResponse<D>>;
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, search) {
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 (model, options) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c2-mongoose",
3
- "version": "2.1.229",
3
+ "version": "2.1.231",
4
4
  "description": "Lib to make any search in database mongoose and use as basic crud",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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>, search?: SearchFlow) {
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(model: mongoose.Model<any>, options: SearchOptions): Promise<SearchResponse<D>> {
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