lemon-core 4.1.14 → 4.2.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/dist/common/test-helper.d.ts +2 -2
- package/dist/common/test-helper.js +24 -26
- package/dist/common/test-helper.js.map +1 -1
- package/dist/controllers/dummy-controller.js +39 -46
- package/dist/controllers/dummy-controller.js.map +1 -1
- package/dist/controllers/general-api-controller.js +95 -100
- package/dist/controllers/general-api-controller.js.map +1 -1
- package/dist/controllers/general-controller.js +81 -82
- package/dist/controllers/general-controller.js.map +1 -1
- package/dist/cores/api/api-service.d.ts +1 -1
- package/dist/cores/api/api-service.js +228 -269
- package/dist/cores/api/api-service.js.map +1 -1
- package/dist/cores/aws/aws-kms-service.d.ts +1 -2
- package/dist/cores/aws/aws-kms-service.js +143 -153
- package/dist/cores/aws/aws-kms-service.js.map +1 -1
- package/dist/cores/aws/aws-s3-service.d.ts +2 -4
- package/dist/cores/aws/aws-s3-service.js +306 -330
- package/dist/cores/aws/aws-s3-service.js.map +1 -1
- package/dist/cores/aws/aws-sns-service.js +147 -153
- package/dist/cores/aws/aws-sns-service.js.map +1 -1
- package/dist/cores/aws/aws-sqs-service.js +149 -170
- package/dist/cores/aws/aws-sqs-service.js.map +1 -1
- package/dist/cores/aws/index.js +10 -20
- package/dist/cores/aws/index.js.map +1 -1
- package/dist/cores/cache/cache-service.d.ts +2 -2
- package/dist/cores/cache/cache-service.js +435 -499
- package/dist/cores/cache/cache-service.js.map +1 -1
- package/dist/cores/config/config-service.d.ts +1 -1
- package/dist/cores/config/config-service.js +56 -63
- package/dist/cores/config/config-service.js.map +1 -1
- package/dist/cores/config/index.js +14 -24
- package/dist/cores/config/index.js.map +1 -1
- package/dist/cores/core-services.d.ts +1 -1
- package/dist/cores/dynamo/dynamo-query-service.js +37 -51
- package/dist/cores/dynamo/dynamo-query-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-scan-service.d.ts +2 -2
- package/dist/cores/dynamo/dynamo-scan-service.js +29 -40
- package/dist/cores/dynamo/dynamo-scan-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-service.d.ts +2 -2
- package/dist/cores/dynamo/dynamo-service.js +528 -601
- package/dist/cores/dynamo/dynamo-service.js.map +1 -1
- package/dist/cores/dynamo/tools/expressions.js +17 -7
- package/dist/cores/dynamo/tools/expressions.js.map +1 -1
- package/dist/cores/dynamo/tools/query.js +142 -127
- package/dist/cores/dynamo/tools/query.js.map +1 -1
- package/dist/cores/dynamo/tools/scan.js +111 -97
- package/dist/cores/dynamo/tools/scan.js.map +1 -1
- package/dist/cores/dynamo/tools/serializer.js +17 -7
- package/dist/cores/dynamo/tools/serializer.js.map +1 -1
- package/dist/cores/dynamo/tools/utils.d.ts +0 -2
- package/dist/cores/dynamo/tools/utils.js.map +1 -1
- package/dist/cores/elastic/elastic6-query-service.js +307 -324
- package/dist/cores/elastic/elastic6-query-service.js.map +1 -1
- package/dist/cores/elastic/elastic6-service.d.ts +3 -3
- package/dist/cores/elastic/elastic6-service.js +568 -647
- package/dist/cores/elastic/elastic6-service.js.map +1 -1
- package/dist/cores/elastic/hangul-service.js +52 -54
- package/dist/cores/elastic/hangul-service.js.map +1 -1
- package/dist/cores/lambda/index.js +42 -36
- package/dist/cores/lambda/index.js.map +1 -1
- package/dist/cores/lambda/lambda-alb-handler.d.ts +2 -2
- package/dist/cores/lambda/lambda-alb-handler.js +59 -72
- package/dist/cores/lambda/lambda-alb-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-cognito-handler.js +10 -19
- package/dist/cores/lambda/lambda-cognito-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-cron-handler.d.ts +1 -1
- package/dist/cores/lambda/lambda-cron-handler.js +14 -23
- package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-dynamo-stream-handler.d.ts +2 -2
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js +57 -67
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-handler.d.ts +22 -22
- package/dist/cores/lambda/lambda-handler.js +93 -106
- package/dist/cores/lambda/lambda-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-notification-handler.d.ts +1 -1
- package/dist/cores/lambda/lambda-notification-handler.js +39 -50
- package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sns-handler.js +79 -88
- package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sqs-handler.js +79 -88
- package/dist/cores/lambda/lambda-sqs-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-web-handler.d.ts +21 -43
- package/dist/cores/lambda/lambda-web-handler.js +392 -482
- package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-wss-handler.js +23 -32
- package/dist/cores/lambda/lambda-wss-handler.js.map +1 -1
- package/dist/cores/protocol/index.js +10 -20
- package/dist/cores/protocol/index.js.map +1 -1
- package/dist/cores/protocol/protocol-service.d.ts +3 -3
- package/dist/cores/protocol/protocol-service.js +235 -227
- package/dist/cores/protocol/protocol-service.js.map +1 -1
- package/dist/cores/storage/http-storage-service.js +65 -85
- package/dist/cores/storage/http-storage-service.js.map +1 -1
- package/dist/cores/storage/model-manager.js +66 -85
- package/dist/cores/storage/model-manager.js.map +1 -1
- package/dist/cores/storage/proxy-storage-service.d.ts +2 -2
- package/dist/cores/storage/proxy-storage-service.js +562 -599
- package/dist/cores/storage/proxy-storage-service.js.map +1 -1
- package/dist/cores/storage/redis-storage-service.js +163 -177
- package/dist/cores/storage/redis-storage-service.js.map +1 -1
- package/dist/cores/storage/storage-service.js +281 -322
- package/dist/cores/storage/storage-service.js.map +1 -1
- package/dist/engine/builder.d.ts +1 -1
- package/dist/engine/builder.js +59 -63
- package/dist/engine/builder.js.map +1 -1
- package/dist/engine/engine.d.ts +4 -4
- package/dist/engine/engine.js +9 -18
- package/dist/engine/engine.js.map +1 -1
- package/dist/engine/types.d.ts +1 -1
- package/dist/engine/utilities.d.ts +14 -10
- package/dist/engine/utilities.js +301 -280
- package/dist/engine/utilities.js.map +1 -1
- package/dist/environ.js +4 -6
- package/dist/environ.js.map +1 -1
- package/dist/extended/abstract-service.js +595 -645
- package/dist/extended/abstract-service.js.map +1 -1
- package/dist/extended/libs/sig-v4.js.map +1 -1
- package/dist/generated/field-registry.d.ts +10 -0
- package/dist/generated/field-registry.js +17 -0
- package/dist/generated/field-registry.js.map +1 -0
- package/dist/helpers/helpers.d.ts +17 -9
- package/dist/helpers/helpers.js +88 -78
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/dynamodb-value.js +2 -3
- package/dist/lib/dynamodb-value.js.map +1 -1
- package/dist/tools/express.js +4 -5
- package/dist/tools/express.js.map +1 -1
- package/dist/tools/tools.d.ts +3 -1
- package/dist/tools/tools.js +14 -21
- package/dist/tools/tools.js.map +1 -1
- package/package.json +19 -18
- package/dist/exec-cli.d.ts +0 -2
- package/dist/exec-cli.js +0 -211
- package/dist/exec-cli.js.map +0 -1
- package/dist/lib/dynamo/expressions.d.ts +0 -14
- package/dist/lib/dynamo/expressions.js +0 -212
- package/dist/lib/dynamo/expressions.js.map +0 -1
- package/dist/lib/dynamo/query.d.ts +0 -43
- package/dist/lib/dynamo/query.js +0 -246
- package/dist/lib/dynamo/query.js.map +0 -1
- package/dist/lib/dynamo/scan.d.ts +0 -33
- package/dist/lib/dynamo/scan.js +0 -172
- package/dist/lib/dynamo/scan.js.map +0 -1
- package/dist/lib/dynamo/serializer.d.ts +0 -12
- package/dist/lib/dynamo/serializer.js +0 -243
- package/dist/lib/dynamo/serializer.js.map +0 -1
- package/dist/lib/dynamo/utils.d.ts +0 -15
- package/dist/lib/dynamo/utils.js +0 -129
- package/dist/lib/dynamo/utils.js.map +0 -1
- package/dist/tools/shared.d.ts +0 -37
- package/dist/tools/shared.js +0 -130
- package/dist/tools/shared.js.map +0 -1
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -34,260 +25,12 @@ const NS = engine_1.$U.NS('ES6Q', 'green'); // NAMESPACE TO BE PRINTED.
|
|
|
34
25
|
* - support simple query like range search.
|
|
35
26
|
*/
|
|
36
27
|
class Elastic6QueryService {
|
|
28
|
+
service;
|
|
37
29
|
/**
|
|
38
30
|
* use query w/ the given search-service.
|
|
39
31
|
* @param service the origin search-service to use.
|
|
40
32
|
*/
|
|
41
33
|
constructor(service) {
|
|
42
|
-
/**
|
|
43
|
-
* say hello of identity.
|
|
44
|
-
*/
|
|
45
|
-
this.hello = () => `elastic6-query-service:${this.options.indexName}`;
|
|
46
|
-
/**
|
|
47
|
-
* build query parameter from search param.
|
|
48
|
-
*/
|
|
49
|
-
this.buildQueryBody = (param) => {
|
|
50
|
-
//* parameters.
|
|
51
|
-
let $query = null;
|
|
52
|
-
let $source = null;
|
|
53
|
-
let $page = -1;
|
|
54
|
-
let $limit = -1;
|
|
55
|
-
let $A = ''; // Aggregation
|
|
56
|
-
let $O = ''; // OrderBy
|
|
57
|
-
let $H = ''; // Highlight
|
|
58
|
-
//* build query.
|
|
59
|
-
const queries = Object.keys(param).reduce((list, key) => {
|
|
60
|
-
let val = param[key];
|
|
61
|
-
// ignore internal values.
|
|
62
|
-
if (key.startsWith('_'))
|
|
63
|
-
return list;
|
|
64
|
-
// _log(NS, `>> param[${key}] = `, val);
|
|
65
|
-
if (key === '$query') {
|
|
66
|
-
$query = {
|
|
67
|
-
query: typeof val === 'object' ? val : typeof val === 'string' ? JSON.parse(val) : `${val || ''}`,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
else if (key === '$limit') {
|
|
71
|
-
$limit = engine_1.$U.N(val, 0);
|
|
72
|
-
}
|
|
73
|
-
else if (key === '$page') {
|
|
74
|
-
$page = engine_1.$U.N(val, 0);
|
|
75
|
-
}
|
|
76
|
-
else if (key === '$Q') {
|
|
77
|
-
if (!val) {
|
|
78
|
-
//NOP;
|
|
79
|
-
}
|
|
80
|
-
else if (typeof val === 'object') {
|
|
81
|
-
// ONLY IF object. use it as raw query.
|
|
82
|
-
$query = val;
|
|
83
|
-
}
|
|
84
|
-
else if (typeof val === 'string' && val.startsWith('{') && val.endsWith('}')) {
|
|
85
|
-
// might be the json data.
|
|
86
|
-
$query = JSON.parse(val);
|
|
87
|
-
}
|
|
88
|
-
else if (typeof val === 'string') {
|
|
89
|
-
// might be query string.
|
|
90
|
-
//* escape queries..
|
|
91
|
-
// + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
|
|
92
|
-
// val = val.replace(/([\(\)])/ig,'\\$1'); //TODO - 이걸 무시하면, 중복 조건 검색에 문제가 생김, 하여 일단 안하는걸루. @180828.
|
|
93
|
-
list.push(`(${val})`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else if (key === '$A') {
|
|
97
|
-
$A = `${val}`.trim(); // ',' delimited terms to count
|
|
98
|
-
}
|
|
99
|
-
else if (key === '$O') {
|
|
100
|
-
$O = `${val}`.trim(); // ',' delimited terms to order
|
|
101
|
-
}
|
|
102
|
-
else if (key === '$H') {
|
|
103
|
-
$H = `${val}`.trim(); // ',' delimited terms to highlight
|
|
104
|
-
}
|
|
105
|
-
else if (key === '$source') {
|
|
106
|
-
// returned source fields set. '*', 'obj.*', '!abc'
|
|
107
|
-
if (val === '*') {
|
|
108
|
-
// all.
|
|
109
|
-
$source = '*';
|
|
110
|
-
}
|
|
111
|
-
else if (typeof val === 'string' && val.indexOf !== undefined) {
|
|
112
|
-
// string array set.
|
|
113
|
-
const vals = val.split(',') || [];
|
|
114
|
-
const $includes = [];
|
|
115
|
-
const $excludes = [];
|
|
116
|
-
vals.forEach(val => {
|
|
117
|
-
val = `${val || ''}`.trim();
|
|
118
|
-
if (!val)
|
|
119
|
-
return;
|
|
120
|
-
if (val.startsWith('!')) {
|
|
121
|
-
$excludes.push(val.substr(1));
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
$includes.push(val);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
$source = { includes: $includes, excludes: $excludes };
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
$source = val;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else if (key === '$exist' || key === '$exists') {
|
|
134
|
-
(Array.isArray(val) ? val : `${val}`.split(',') || []).forEach((val) => {
|
|
135
|
-
val = `${val || ''}`.trim();
|
|
136
|
-
if (!val)
|
|
137
|
-
return;
|
|
138
|
-
if (val.startsWith('!')) {
|
|
139
|
-
list.push('NOT _exists_:' + val.substr(1));
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
list.push('_exists_:' + val);
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
//* escape if there is ' ' except like '(a AND B)'
|
|
148
|
-
const escape_val = (val) => {
|
|
149
|
-
if (typeof val === 'string' && val === '') {
|
|
150
|
-
return '"' + val + '"';
|
|
151
|
-
}
|
|
152
|
-
else if (val && typeof val === 'string') {
|
|
153
|
-
if (val.startsWith('(') && val.endsWith(')')) {
|
|
154
|
-
// nop
|
|
155
|
-
}
|
|
156
|
-
else if (val.startsWith('"') && val.endsWith('"')) {
|
|
157
|
-
// must be string block
|
|
158
|
-
return val;
|
|
159
|
-
}
|
|
160
|
-
else if (val.indexOf(',') > 0) {
|
|
161
|
-
// list of array.
|
|
162
|
-
return val.split(',').map(s => {
|
|
163
|
-
return (s || '').trim();
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
else if (
|
|
167
|
-
// special chars
|
|
168
|
-
val.indexOf(' ') >= 0 ||
|
|
169
|
-
val.indexOf('\n') >= 0 ||
|
|
170
|
-
val.indexOf(':') >= 0 ||
|
|
171
|
-
val.indexOf('\\') >= 0 ||
|
|
172
|
-
val.indexOf('#') >= 0 ||
|
|
173
|
-
val.indexOf('^') >= 0) {
|
|
174
|
-
const str = val.replace(/([\"\'])/gi, '\\$1'); // replace '"' -> '\"'
|
|
175
|
-
return '"' + str + '"';
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return val;
|
|
179
|
-
};
|
|
180
|
-
val = escape_val(val);
|
|
181
|
-
//* add to query-list.
|
|
182
|
-
if (key.startsWith('!')) {
|
|
183
|
-
if (val) {
|
|
184
|
-
if (Array.isArray(val)) {
|
|
185
|
-
const vals = val.map((_) => escape_val(_));
|
|
186
|
-
list.push(key.substr(1) + ':(NOT (' + vals.join(' OR ') + '))');
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
list.push(key.substr(1) + ':(NOT ' + val + ')');
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
list.push('_exists_:' + key.substr(1));
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
else if (key.startsWith('#')) {
|
|
197
|
-
// projection.
|
|
198
|
-
$source = $source || { includes: [], excludes: [] };
|
|
199
|
-
if ($source && $source.includes) {
|
|
200
|
-
$source.includes.push(key.substr(1));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
else if (val === undefined) {
|
|
204
|
-
//* nop
|
|
205
|
-
}
|
|
206
|
-
else if (val && Array.isArray(val)) {
|
|
207
|
-
// list.push('(' + val.map(val => `${key}:${val}`).join(' OR ') + ')');
|
|
208
|
-
list.push(`${key}:` + '(' + val.map((val) => `${escape_val(val)}`).join(' OR ') + ')');
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
list.push(`${key}:${val}`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return list;
|
|
215
|
-
}, []);
|
|
216
|
-
//* prepare returned body.
|
|
217
|
-
const $body = $query
|
|
218
|
-
? $query
|
|
219
|
-
: (queries.length && { query: { query_string: { query: queries.join(' AND ') } } }) || {}; // $query 이게 있으면 그냥 이걸 이용.
|
|
220
|
-
//* Aggregation.
|
|
221
|
-
if ($A) {
|
|
222
|
-
// const $aggs = {
|
|
223
|
-
// // "types_count" : { "value_count" : { "field" : "brand" } }
|
|
224
|
-
// "types_count" : { "terms" : { "field" : "brand" } }
|
|
225
|
-
// }
|
|
226
|
-
const $aggs = $A.split(',').reduce(($a, val) => {
|
|
227
|
-
val = ('' + val).trim();
|
|
228
|
-
if (val) {
|
|
229
|
-
if (val.indexOf(':') > 0) {
|
|
230
|
-
// must be size.
|
|
231
|
-
const [nm, size] = val.split(':', 2);
|
|
232
|
-
$a[nm] = { terms: { field: nm, size: parseInt(size) } };
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
$a[val] = { terms: { field: val } };
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return $a;
|
|
239
|
-
}, {});
|
|
240
|
-
$body['aggs'] = $aggs;
|
|
241
|
-
}
|
|
242
|
-
//* OrderBy.
|
|
243
|
-
if ($O) {
|
|
244
|
-
//see sorting: see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html.
|
|
245
|
-
const $sort = $O.split(',').reduce(($a, val) => {
|
|
246
|
-
val = ('' + val).trim();
|
|
247
|
-
if (val) {
|
|
248
|
-
let name = val;
|
|
249
|
-
let asc = true;
|
|
250
|
-
if (val.startsWith('!')) {
|
|
251
|
-
// reverse
|
|
252
|
-
name = val.slice(1);
|
|
253
|
-
asc = false;
|
|
254
|
-
}
|
|
255
|
-
if (name) {
|
|
256
|
-
$a.push({ [name]: { order: asc ? 'asc' : 'desc' } });
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return $a;
|
|
260
|
-
}, []);
|
|
261
|
-
if ($sort.length) {
|
|
262
|
-
$body.sort = $sort;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
//* Highlight.
|
|
266
|
-
if ($H) {
|
|
267
|
-
const $highlight = $H.split(',').reduce(($h, val) => {
|
|
268
|
-
val = ('' + val).trim();
|
|
269
|
-
if (val) {
|
|
270
|
-
$h[val] = { type: 'unified' };
|
|
271
|
-
}
|
|
272
|
-
return $h;
|
|
273
|
-
}, {});
|
|
274
|
-
$body['highlight'] = {};
|
|
275
|
-
$body['highlight']['fields'] = $highlight;
|
|
276
|
-
}
|
|
277
|
-
//* if valid limit, then paginating.
|
|
278
|
-
if ($limit > -1) {
|
|
279
|
-
$body.size = $limit;
|
|
280
|
-
if ($page > -1) {
|
|
281
|
-
// starts from 0
|
|
282
|
-
$body.from = $page * $limit;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
//* field projection with _source parameter.
|
|
286
|
-
if ($source !== null)
|
|
287
|
-
$body._source = $source;
|
|
288
|
-
//* returns body.
|
|
289
|
-
return $body;
|
|
290
|
-
};
|
|
291
34
|
const options = service.options;
|
|
292
35
|
if (!options.indexName)
|
|
293
36
|
throw new Error('.indexName is required');
|
|
@@ -299,6 +42,10 @@ class Elastic6QueryService {
|
|
|
299
42
|
get options() {
|
|
300
43
|
return this.service.options;
|
|
301
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* say hello of identity.
|
|
47
|
+
*/
|
|
48
|
+
hello = () => `elastic6-query-service:${this.options.indexName}`;
|
|
302
49
|
/**
|
|
303
50
|
* query all by id.
|
|
304
51
|
*
|
|
@@ -306,18 +53,16 @@ class Elastic6QueryService {
|
|
|
306
53
|
* @param limit
|
|
307
54
|
* @param isDesc
|
|
308
55
|
*/
|
|
309
|
-
queryAll(id, limit, isDesc) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
return this.searchSimple(param);
|
|
320
|
-
});
|
|
56
|
+
async queryAll(id, limit, isDesc) {
|
|
57
|
+
const { idName } = this.options;
|
|
58
|
+
const param = {
|
|
59
|
+
[idName]: id,
|
|
60
|
+
};
|
|
61
|
+
if (limit !== undefined)
|
|
62
|
+
param['$limit'] = limit;
|
|
63
|
+
if (isDesc !== undefined)
|
|
64
|
+
param['$O'] = (isDesc ? '!' : '') + id;
|
|
65
|
+
return this.searchSimple(param);
|
|
321
66
|
}
|
|
322
67
|
/**
|
|
323
68
|
* search in simple mode
|
|
@@ -352,20 +97,18 @@ class Elastic6QueryService {
|
|
|
352
97
|
*
|
|
353
98
|
* @param param search param
|
|
354
99
|
*/
|
|
355
|
-
searchSimple(param) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
return this.asQueryResult(body, res);
|
|
368
|
-
});
|
|
100
|
+
async searchSimple(param) {
|
|
101
|
+
if (!param)
|
|
102
|
+
throw new Error('@param (SimpleSearchParam) is required');
|
|
103
|
+
const { indexName } = this.options;
|
|
104
|
+
(0, engine_1._log)(NS, `- searchSimple(${indexName})....`);
|
|
105
|
+
(0, engine_1._log)(NS, `> param =`, engine_1.$U.json(param));
|
|
106
|
+
//* build query body.
|
|
107
|
+
const body = this.buildQueryBody(param);
|
|
108
|
+
//* search via client
|
|
109
|
+
const res = await this.search(body);
|
|
110
|
+
//* convert to query-result.
|
|
111
|
+
return this.asQueryResult(body, res);
|
|
369
112
|
}
|
|
370
113
|
/**
|
|
371
114
|
* search with raw query language.
|
|
@@ -373,12 +116,10 @@ class Elastic6QueryService {
|
|
|
373
116
|
* @param body SearchBody.
|
|
374
117
|
* @returns results.
|
|
375
118
|
*/
|
|
376
|
-
search(body, searchType) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return this.service.searchRaw(body, searchType);
|
|
381
|
-
});
|
|
119
|
+
async search(body, searchType) {
|
|
120
|
+
if (!body)
|
|
121
|
+
throw new Error('@body (SearchBody) is required');
|
|
122
|
+
return this.service.searchRaw(body, searchType);
|
|
382
123
|
}
|
|
383
124
|
/**
|
|
384
125
|
* convert result as `QueryResult`
|
|
@@ -387,14 +128,13 @@ class Elastic6QueryService {
|
|
|
387
128
|
* @returns QueryResult
|
|
388
129
|
*/
|
|
389
130
|
asQueryResult(body, res) {
|
|
390
|
-
|
|
391
|
-
const size = engine_1.$U.N(body === null || body === void 0 ? void 0 : body.size, 10);
|
|
131
|
+
const size = engine_1.$U.N(body?.size, 10);
|
|
392
132
|
//* extract for result.
|
|
393
|
-
const hits = res
|
|
133
|
+
const hits = res?.hits;
|
|
394
134
|
if (typeof hits !== 'object')
|
|
395
135
|
throw new Error(`.hits (object) is required - hists:${engine_1.$U.json(hits)}`);
|
|
396
|
-
const total = engine_1.$U.N(typeof
|
|
397
|
-
const last =
|
|
136
|
+
const total = engine_1.$U.N(typeof hits.total?.value === 'number' ? hits.total?.value : hits.total, 0); // since v7.x
|
|
137
|
+
const last = hits?.hits.length === size ? hits.hits[size - 1]?.sort : undefined;
|
|
398
138
|
const list = ((hits && hits.hits) || []).map((N) => {
|
|
399
139
|
const id = N && N._id; // id of elastic-search
|
|
400
140
|
const score = N && N._score; // search score.
|
|
@@ -408,7 +148,7 @@ class Elastic6QueryService {
|
|
|
408
148
|
return source;
|
|
409
149
|
});
|
|
410
150
|
const result = { list, total, last };
|
|
411
|
-
if (res
|
|
151
|
+
if (res?.aggregations) {
|
|
412
152
|
const $aggregations = res.aggregations || {};
|
|
413
153
|
result.aggregations = Object.keys($aggregations).reduce((aggrs, field) => {
|
|
414
154
|
const { doc_count_error_upper_bound: docCountError = 0, sum_other_doc_count: docSkippedCount = 0, buckets, } = res.aggregations[field];
|
|
@@ -472,39 +212,282 @@ class Elastic6QueryService {
|
|
|
472
212
|
* search item in Search-as-You-Type way
|
|
473
213
|
* @param param AutocompleteSearchParam
|
|
474
214
|
*/
|
|
475
|
-
searchAutocomplete(param) {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
215
|
+
async searchAutocomplete(param) {
|
|
216
|
+
const { field, query, body } = this.asSearchBody(param);
|
|
217
|
+
const res = await this.service.searchRaw(body);
|
|
218
|
+
const result = this.asQueryResult(body, res);
|
|
219
|
+
// highlighting result manually
|
|
220
|
+
let list = result.list;
|
|
221
|
+
if (param.$highlight) {
|
|
222
|
+
// prepare tag name to wrap highlighted text
|
|
223
|
+
const tagName = typeof param.$highlight == 'string' ? param.$highlight : 'em';
|
|
224
|
+
// create a regular expression which has optional whitespaces between each character
|
|
225
|
+
// e.g. 'COVID-19' => /C *O *V *I *D *- *1 *9/i
|
|
226
|
+
const regexp = new RegExp([...query.replace(/\s/g, '')].join(' *'), 'i');
|
|
227
|
+
// try to match regular expression with items found
|
|
228
|
+
list = result.list.map((item) => {
|
|
229
|
+
const target = `${item[field] || ''}`;
|
|
230
|
+
const match = target.match(regexp);
|
|
231
|
+
if (match) {
|
|
232
|
+
item._highlight =
|
|
233
|
+
target.slice(0, match.index) +
|
|
234
|
+
`<${tagName}>${match[0]}</${tagName}>` +
|
|
235
|
+
target.slice(match.index + match[0].length);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
item._highlight = target;
|
|
239
|
+
}
|
|
240
|
+
return item;
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
//* finally, override list.
|
|
244
|
+
return { ...result, list };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* build query parameter from search param.
|
|
248
|
+
*/
|
|
249
|
+
buildQueryBody = (param) => {
|
|
250
|
+
//* parameters.
|
|
251
|
+
let $query = null;
|
|
252
|
+
let $source = null;
|
|
253
|
+
let $page = -1;
|
|
254
|
+
let $limit = -1;
|
|
255
|
+
let $A = ''; // Aggregation
|
|
256
|
+
let $O = ''; // OrderBy
|
|
257
|
+
let $H = ''; // Highlight
|
|
258
|
+
//* build query.
|
|
259
|
+
const queries = Object.keys(param).reduce((list, key) => {
|
|
260
|
+
let val = param[key];
|
|
261
|
+
// ignore internal values.
|
|
262
|
+
if (key.startsWith('_'))
|
|
263
|
+
return list;
|
|
264
|
+
// _log(NS, `>> param[${key}] = `, val);
|
|
265
|
+
if (key === '$query') {
|
|
266
|
+
$query = {
|
|
267
|
+
query: typeof val === 'object' ? val : typeof val === 'string' ? JSON.parse(val) : `${val || ''}`,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
else if (key === '$limit') {
|
|
271
|
+
$limit = engine_1.$U.N(val, 0);
|
|
272
|
+
}
|
|
273
|
+
else if (key === '$page') {
|
|
274
|
+
$page = engine_1.$U.N(val, 0);
|
|
275
|
+
}
|
|
276
|
+
else if (key === '$Q') {
|
|
277
|
+
if (!val) {
|
|
278
|
+
//NOP;
|
|
279
|
+
}
|
|
280
|
+
else if (typeof val === 'object') {
|
|
281
|
+
// ONLY IF object. use it as raw query.
|
|
282
|
+
$query = val;
|
|
283
|
+
}
|
|
284
|
+
else if (typeof val === 'string' && val.startsWith('{') && val.endsWith('}')) {
|
|
285
|
+
// might be the json data.
|
|
286
|
+
$query = JSON.parse(val);
|
|
287
|
+
}
|
|
288
|
+
else if (typeof val === 'string') {
|
|
289
|
+
// might be query string.
|
|
290
|
+
//* escape queries..
|
|
291
|
+
// + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
|
|
292
|
+
// val = val.replace(/([\(\)])/ig,'\\$1'); //TODO - 이걸 무시하면, 중복 조건 검색에 문제가 생김, 하여 일단 안하는걸루. @180828.
|
|
293
|
+
list.push(`(${val})`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else if (key === '$A') {
|
|
297
|
+
$A = `${val}`.trim(); // ',' delimited terms to count
|
|
298
|
+
}
|
|
299
|
+
else if (key === '$O') {
|
|
300
|
+
$O = `${val}`.trim(); // ',' delimited terms to order
|
|
301
|
+
}
|
|
302
|
+
else if (key === '$H') {
|
|
303
|
+
$H = `${val}`.trim(); // ',' delimited terms to highlight
|
|
304
|
+
}
|
|
305
|
+
else if (key === '$source') {
|
|
306
|
+
// returned source fields set. '*', 'obj.*', '!abc'
|
|
307
|
+
if (val === '*') {
|
|
308
|
+
// all.
|
|
309
|
+
$source = '*';
|
|
310
|
+
}
|
|
311
|
+
else if (typeof val === 'string' && val.indexOf !== undefined) {
|
|
312
|
+
// string array set.
|
|
313
|
+
const vals = val.split(',') || [];
|
|
314
|
+
const $includes = [];
|
|
315
|
+
const $excludes = [];
|
|
316
|
+
vals.forEach(val => {
|
|
317
|
+
val = `${val || ''}`.trim();
|
|
318
|
+
if (!val)
|
|
319
|
+
return;
|
|
320
|
+
if (val.startsWith('!')) {
|
|
321
|
+
$excludes.push(val.substr(1));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
$includes.push(val);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
$source = { includes: $includes, excludes: $excludes };
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
$source = val;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else if (key === '$exist' || key === '$exists') {
|
|
334
|
+
(Array.isArray(val) ? val : `${val}`.split(',') || []).forEach((val) => {
|
|
335
|
+
val = `${val || ''}`.trim();
|
|
336
|
+
if (!val)
|
|
337
|
+
return;
|
|
338
|
+
if (val.startsWith('!')) {
|
|
339
|
+
list.push('NOT _exists_:' + val.substr(1));
|
|
497
340
|
}
|
|
498
341
|
else {
|
|
499
|
-
|
|
342
|
+
list.push('_exists_:' + val);
|
|
500
343
|
}
|
|
501
|
-
return item;
|
|
502
344
|
});
|
|
503
345
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
346
|
+
else {
|
|
347
|
+
//* escape if there is ' ' except like '(a AND B)'
|
|
348
|
+
const escape_val = (val) => {
|
|
349
|
+
if (typeof val === 'string' && val === '') {
|
|
350
|
+
return '"' + val + '"';
|
|
351
|
+
}
|
|
352
|
+
else if (val && typeof val === 'string') {
|
|
353
|
+
if (val.startsWith('(') && val.endsWith(')')) {
|
|
354
|
+
// nop
|
|
355
|
+
}
|
|
356
|
+
else if (val.startsWith('"') && val.endsWith('"')) {
|
|
357
|
+
// must be string block
|
|
358
|
+
return val;
|
|
359
|
+
}
|
|
360
|
+
else if (val.indexOf(',') > 0) {
|
|
361
|
+
// list of array.
|
|
362
|
+
return val.split(',').map(s => {
|
|
363
|
+
return (s || '').trim();
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
else if (
|
|
367
|
+
// special chars
|
|
368
|
+
val.indexOf(' ') >= 0 ||
|
|
369
|
+
val.indexOf('\n') >= 0 ||
|
|
370
|
+
val.indexOf(':') >= 0 ||
|
|
371
|
+
val.indexOf('\\') >= 0 ||
|
|
372
|
+
val.indexOf('#') >= 0 ||
|
|
373
|
+
val.indexOf('^') >= 0) {
|
|
374
|
+
const str = val.replace(/([\"\'])/gi, '\\$1'); // replace '"' -> '\"'
|
|
375
|
+
return '"' + str + '"';
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return val;
|
|
379
|
+
};
|
|
380
|
+
val = escape_val(val);
|
|
381
|
+
//* add to query-list.
|
|
382
|
+
if (key.startsWith('!')) {
|
|
383
|
+
if (val) {
|
|
384
|
+
if (Array.isArray(val)) {
|
|
385
|
+
const vals = val.map((_) => escape_val(_));
|
|
386
|
+
list.push(key.substr(1) + ':(NOT (' + vals.join(' OR ') + '))');
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
list.push(key.substr(1) + ':(NOT ' + val + ')');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
list.push('_exists_:' + key.substr(1));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else if (key.startsWith('#')) {
|
|
397
|
+
// projection.
|
|
398
|
+
$source = $source || { includes: [], excludes: [] };
|
|
399
|
+
if ($source && $source.includes) {
|
|
400
|
+
$source.includes.push(key.substr(1));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else if (val === undefined) {
|
|
404
|
+
//* nop
|
|
405
|
+
}
|
|
406
|
+
else if (val && Array.isArray(val)) {
|
|
407
|
+
// list.push('(' + val.map(val => `${key}:${val}`).join(' OR ') + ')');
|
|
408
|
+
list.push(`${key}:` + '(' + val.map((val) => `${escape_val(val)}`).join(' OR ') + ')');
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
list.push(`${key}:${val}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return list;
|
|
415
|
+
}, []);
|
|
416
|
+
//* prepare returned body.
|
|
417
|
+
const $body = $query
|
|
418
|
+
? $query
|
|
419
|
+
: (queries.length && { query: { query_string: { query: queries.join(' AND ') } } }) || {}; // $query 이게 있으면 그냥 이걸 이용.
|
|
420
|
+
//* Aggregation.
|
|
421
|
+
if ($A) {
|
|
422
|
+
// const $aggs = {
|
|
423
|
+
// // "types_count" : { "value_count" : { "field" : "brand" } }
|
|
424
|
+
// "types_count" : { "terms" : { "field" : "brand" } }
|
|
425
|
+
// }
|
|
426
|
+
const $aggs = $A.split(',').reduce(($a, val) => {
|
|
427
|
+
val = ('' + val).trim();
|
|
428
|
+
if (val) {
|
|
429
|
+
if (val.indexOf(':') > 0) {
|
|
430
|
+
// must be size.
|
|
431
|
+
const [nm, size] = val.split(':', 2);
|
|
432
|
+
$a[nm] = { terms: { field: nm, size: parseInt(size) } };
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
$a[val] = { terms: { field: val } };
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return $a;
|
|
439
|
+
}, {});
|
|
440
|
+
$body['aggs'] = $aggs;
|
|
441
|
+
}
|
|
442
|
+
//* OrderBy.
|
|
443
|
+
if ($O) {
|
|
444
|
+
//see sorting: see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html.
|
|
445
|
+
const $sort = $O.split(',').reduce(($a, val) => {
|
|
446
|
+
val = ('' + val).trim();
|
|
447
|
+
if (val) {
|
|
448
|
+
let name = val;
|
|
449
|
+
let asc = true;
|
|
450
|
+
if (val.startsWith('!')) {
|
|
451
|
+
// reverse
|
|
452
|
+
name = val.slice(1);
|
|
453
|
+
asc = false;
|
|
454
|
+
}
|
|
455
|
+
if (name) {
|
|
456
|
+
$a.push({ [name]: { order: asc ? 'asc' : 'desc' } });
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return $a;
|
|
460
|
+
}, []);
|
|
461
|
+
if ($sort.length) {
|
|
462
|
+
$body.sort = $sort;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
//* Highlight.
|
|
466
|
+
if ($H) {
|
|
467
|
+
const $highlight = $H.split(',').reduce(($h, val) => {
|
|
468
|
+
val = ('' + val).trim();
|
|
469
|
+
if (val) {
|
|
470
|
+
$h[val] = { type: 'unified' };
|
|
471
|
+
}
|
|
472
|
+
return $h;
|
|
473
|
+
}, {});
|
|
474
|
+
$body['highlight'] = {};
|
|
475
|
+
$body['highlight']['fields'] = $highlight;
|
|
476
|
+
}
|
|
477
|
+
//* if valid limit, then paginating.
|
|
478
|
+
if ($limit > -1) {
|
|
479
|
+
$body.size = $limit;
|
|
480
|
+
if ($page > -1) {
|
|
481
|
+
// starts from 0
|
|
482
|
+
$body.from = $page * $limit;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
//* field projection with _source parameter.
|
|
486
|
+
if ($source !== null)
|
|
487
|
+
$body._source = $source;
|
|
488
|
+
//* returns body.
|
|
489
|
+
return $body;
|
|
490
|
+
};
|
|
508
491
|
}
|
|
509
492
|
exports.Elastic6QueryService = Elastic6QueryService;
|
|
510
493
|
//# sourceMappingURL=elastic6-query-service.js.map
|