aws-service-stack 0.18.318 → 0.18.320
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/_examples/service/entity/entity-service.js +2 -1
- package/dist/_examples/service/entity/entity-service.js.map +1 -1
- package/dist/model/filter.model.d.ts +31 -0
- package/dist/model/filter.model.js +29 -0
- package/dist/model/filter.model.js.map +1 -1
- package/dist/repositories/base-es.repo.d.ts +4 -1
- package/dist/repositories/base-es.repo.interface.d.ts +4 -1
- package/dist/repositories/base-es.repo.interface.js.map +1 -1
- package/dist/repositories/base-es.repo.js +9 -4
- package/dist/repositories/base-es.repo.js.map +1 -1
- package/dist/service/crud.service.d.ts +4 -1
- package/dist/service/crud.service.interface.d.ts +4 -1
- package/dist/service/crud.service.interface.js.map +1 -1
- package/dist/service/crud.service.js +2 -2
- package/dist/service/crud.service.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/opensearch/opensearch.parser.aggs.d.ts +8 -0
- package/dist/utils/opensearch/opensearch.parser.aggs.js +66 -0
- package/dist/utils/opensearch/opensearch.parser.aggs.js.map +1 -0
- package/dist/utils/opensearch/opensearch.parser.d.ts +13 -0
- package/dist/utils/opensearch/opensearch.parser.js +62 -0
- package/dist/utils/opensearch/opensearch.parser.js.map +1 -0
- package/dist/utils/opensearch/opensearch.parser.keyword.d.ts +13 -0
- package/dist/utils/opensearch/opensearch.parser.keyword.js +61 -0
- package/dist/utils/opensearch/opensearch.parser.keyword.js.map +1 -0
- package/dist/utils/opensearch/opensearch.parser.query.map.d.ts +5 -0
- package/dist/utils/opensearch/opensearch.parser.query.map.js +39 -0
- package/dist/utils/opensearch/opensearch.parser.query.map.js.map +1 -0
- package/dist/utils/opensearch/opensearch.parser.sort.d.ts +1 -0
- package/dist/utils/opensearch/opensearch.parser.sort.js +22 -0
- package/dist/utils/opensearch/opensearch.parser.sort.js.map +1 -0
- package/dist/utils/opensearch/opensearch.parser.utils.d.ts +1 -0
- package/dist/utils/opensearch/opensearch.parser.utils.js +47 -0
- package/dist/utils/opensearch/opensearch.parser.utils.js.map +1 -0
- package/dist/utils/opensearch/opensearch.transform.d.ts +1 -0
- package/dist/utils/opensearch/opensearch.transform.js +48 -0
- package/dist/utils/opensearch/opensearch.transform.js.map +1 -0
- package/package.json +1 -1
- package/dist/utils/opensearch.parser.d.ts +0 -37
- package/dist/utils/opensearch.parser.js +0 -226
- package/dist/utils/opensearch.parser.js.map +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildSearchQueryOS = buildSearchQueryOS;
|
|
4
|
+
const types_1 = require("../../model/index.js");
|
|
5
|
+
const opensearch_parser_keyword_1 = require("./opensearch.parser.keyword");
|
|
6
|
+
const opensearch_parser_sort_1 = require("./opensearch.parser.sort");
|
|
7
|
+
const opensearch_parser_query_map_1 = require("./opensearch.parser.query.map");
|
|
8
|
+
const opensearch_parser_utils_1 = require("./opensearch.parser.utils");
|
|
9
|
+
const opensearch_utils_1 = require("../opensearch.utils");
|
|
10
|
+
const opensearch_parser_aggs_1 = require("./opensearch.parser.aggs");
|
|
11
|
+
// ---------------- Main Function ----------------
|
|
12
|
+
function buildSearchQueryOS(queryParams, opensearchIndex) {
|
|
13
|
+
const filters = (0, opensearch_parser_utils_1.parseQueryString)(queryParams);
|
|
14
|
+
const filterMap = {}; // merge range per field
|
|
15
|
+
const boolQuery = {
|
|
16
|
+
must: [],
|
|
17
|
+
must_not: [],
|
|
18
|
+
filter: [],
|
|
19
|
+
should: [],
|
|
20
|
+
minimum_should_match: undefined,
|
|
21
|
+
};
|
|
22
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
23
|
+
if (!value)
|
|
24
|
+
continue;
|
|
25
|
+
const [field, boolQueryType = types_1.BoolQueryTypeOS.eq] = key.split("__");
|
|
26
|
+
const fn = opensearch_parser_query_map_1.boolQueryMap[boolQueryType];
|
|
27
|
+
if (!fn)
|
|
28
|
+
continue;
|
|
29
|
+
// Range filters
|
|
30
|
+
if (boolQueryType === types_1.RangeTypeOS.gte || boolQueryType === types_1.RangeTypeOS.lte) {
|
|
31
|
+
const existing = filterMap[field]?.range;
|
|
32
|
+
filterMap[field] = fn(field, value, existing);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Other filters
|
|
36
|
+
const builtQuery = fn(field, value);
|
|
37
|
+
if (builtQuery.negation)
|
|
38
|
+
boolQuery.must_not.push(builtQuery.query);
|
|
39
|
+
else
|
|
40
|
+
boolQuery.must.push(builtQuery?.query ? builtQuery.query : builtQuery);
|
|
41
|
+
}
|
|
42
|
+
const filter = Object.values(filterMap);
|
|
43
|
+
if (filter.length)
|
|
44
|
+
boolQuery.filter = filter;
|
|
45
|
+
(0, opensearch_parser_keyword_1.buildSearchKeyword)(queryParams, boolQuery);
|
|
46
|
+
const { size, from } = (0, opensearch_utils_1.calculatePagination)(queryParams);
|
|
47
|
+
const aggs = (0, opensearch_parser_aggs_1.buildAggregations)(queryParams);
|
|
48
|
+
console.log("aggs", aggs);
|
|
49
|
+
return {
|
|
50
|
+
index: opensearchIndex,
|
|
51
|
+
body: {
|
|
52
|
+
query: {
|
|
53
|
+
bool: boolQuery,
|
|
54
|
+
},
|
|
55
|
+
aggs: aggs,
|
|
56
|
+
size: size ?? 25,
|
|
57
|
+
from: from ?? 0,
|
|
58
|
+
sort: (0, opensearch_parser_sort_1.buildSortOS)(queryParams),
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=opensearch.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.parser.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.ts"],"names":[],"mappings":";;AASA,gDAyDC;AAlED,2CAA4E;AAC5E,2EAAiE;AACjE,qEAAuD;AACvD,+EAA6D;AAC7D,uEAA6D;AAC7D,0DAA0D;AAC1D,qEAA6D;AAE7D,kDAAkD;AAClD,SAAgB,kBAAkB,CAAC,WAAW,EAAE,eAAuB;IACrE,MAAM,OAAO,GAAG,IAAA,0CAAgB,EAAC,WAAW,CAAC,CAAC;IAE9C,MAAM,SAAS,GAAwB,EAAE,CAAC,CAAC,wBAAwB;IAEnE,MAAM,SAAS,GAAgB;QAC7B,IAAI,EAAE,EAAE;QACR,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;QACV,oBAAoB,EAAE,SAAS;KAChC,CAAC;IAEF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,uBAAe,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,EAAE,GAAG,0CAAY,CAAC,aAAa,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE;YAAE,SAAS;QAElB,gBAAgB;QAChB,IAAI,aAAa,KAAK,mBAAW,CAAC,GAAG,IAAI,aAAa,KAAK,mBAAW,CAAC,GAAG,EAAE,CAAC;YAC3E,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;YACzC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC9C,SAAS;QACX,CAAC;QAED,gBAAgB;QAChB,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,IAAI,UAAU,CAAC,QAAQ;YAAE,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;;YAC9D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAExC,IAAI,MAAM,CAAC,MAAM;QAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAE7C,IAAA,8CAAkB,EAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAE3C,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAA,sCAAmB,EAAC,WAAW,CAAC,CAAC;IAExD,MAAM,IAAI,GAAG,IAAA,0CAAiB,EAAC,WAAW,CAAC,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE1B,OAAO;QACL,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE;YACJ,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;aAChB;YACD,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,IAAI,IAAI,EAAE;YAChB,IAAI,EAAE,IAAI,IAAI,CAAC;YACf,IAAI,EAAE,IAAA,oCAAW,EAAC,WAAW,CAAC;SAC/B;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { BoolQueryOS, BoolQueryTypeOS, RangeTypeOS } from \"@chinggis/types\";\nimport { buildSearchKeyword } from \"./opensearch.parser.keyword\";\nimport { buildSortOS } from \"./opensearch.parser.sort\";\nimport { boolQueryMap } from \"./opensearch.parser.query.map\";\nimport { parseQueryString } from \"./opensearch.parser.utils\";\nimport { calculatePagination } from \"../opensearch.utils\";\nimport { buildAggregations } from \"./opensearch.parser.aggs\";\n\n// ---------------- Main Function ----------------\nexport function buildSearchQueryOS(queryParams, opensearchIndex: string) {\n const filters = parseQueryString(queryParams);\n\n const filterMap: Record<string, any> = {}; // merge range per field\n\n const boolQuery: BoolQueryOS = {\n must: [],\n must_not: [],\n filter: [],\n should: [],\n minimum_should_match: undefined,\n };\n\n for (const [key, value] of Object.entries(filters)) {\n if (!value) continue;\n\n const [field, boolQueryType = BoolQueryTypeOS.eq] = key.split(\"__\");\n const fn = boolQueryMap[boolQueryType];\n if (!fn) continue;\n\n // Range filters\n if (boolQueryType === RangeTypeOS.gte || boolQueryType === RangeTypeOS.lte) {\n const existing = filterMap[field]?.range;\n filterMap[field] = fn(field, value, existing);\n continue;\n }\n\n // Other filters\n const builtQuery = fn(field, value);\n if (builtQuery.negation) boolQuery.must_not.push(builtQuery.query);\n else boolQuery.must.push(builtQuery?.query ? builtQuery.query : builtQuery);\n }\n\n const filter = Object.values(filterMap);\n\n if (filter.length) boolQuery.filter = filter;\n\n buildSearchKeyword(queryParams, boolQuery);\n\n const { size, from } = calculatePagination(queryParams);\n\n const aggs = buildAggregations(queryParams);\n\n console.log(\"aggs\", aggs);\n\n return {\n index: opensearchIndex,\n body: {\n query: {\n bool: boolQuery,\n },\n aggs: aggs,\n size: size ?? 25,\n from: from ?? 0,\n sort: buildSortOS(queryParams),\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function buildSearchKeyword(queryParams: string, boolQuery: {
|
|
2
|
+
must: Array<any>;
|
|
3
|
+
must_not: Array<any>;
|
|
4
|
+
filter: Array<any>;
|
|
5
|
+
should: Array<any>;
|
|
6
|
+
minimum_should_match?: number;
|
|
7
|
+
}): {
|
|
8
|
+
must: Array<any>;
|
|
9
|
+
must_not: Array<any>;
|
|
10
|
+
filter: Array<any>;
|
|
11
|
+
should: Array<any>;
|
|
12
|
+
minimum_should_match?: number;
|
|
13
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildSearchKeyword = buildSearchKeyword;
|
|
4
|
+
const types_1 = require("../../model/index.js");
|
|
5
|
+
function buildSearchKeyword(queryParams, boolQuery) {
|
|
6
|
+
const params = new URLSearchParams(queryParams);
|
|
7
|
+
const search = params.get("search");
|
|
8
|
+
const fieldsRaw = params.get("searchFields");
|
|
9
|
+
const operator = (params.get("searchOperator") || types_1.SearchOperatorOS.OR).toLowerCase();
|
|
10
|
+
if (!search || !fieldsRaw) {
|
|
11
|
+
return boolQuery;
|
|
12
|
+
}
|
|
13
|
+
const fields = stringSplitter(fieldsRaw);
|
|
14
|
+
for (const field of fields) {
|
|
15
|
+
const query = buildSearchKeywordQuery(field, search);
|
|
16
|
+
if (query) {
|
|
17
|
+
if (operator === types_1.SearchOperatorOS.OR) {
|
|
18
|
+
boolQuery.should.push(query);
|
|
19
|
+
boolQuery.minimum_should_match = 1;
|
|
20
|
+
}
|
|
21
|
+
if (operator === types_1.SearchOperatorOS.AND) {
|
|
22
|
+
boolQuery.must.push(query);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return boolQuery;
|
|
27
|
+
}
|
|
28
|
+
function buildSearchKeywordQuery(field, searchKeyword) {
|
|
29
|
+
if (!searchKeyword || searchKeyword.trim() === "")
|
|
30
|
+
return undefined;
|
|
31
|
+
// 1. Олон *-уудыг нэг * болгох
|
|
32
|
+
let cleanedKeyword = searchKeyword.replace(/\*+/g, "*").trim();
|
|
33
|
+
if (!cleanedKeyword.endsWith("*")) {
|
|
34
|
+
// 2. Хэрвээ keyword-ын төгсгөлд * байхгүй бол автоматаар * нэмэх
|
|
35
|
+
cleanedKeyword += "*";
|
|
36
|
+
}
|
|
37
|
+
// word-д *-оор эхэлсэн бол wildcard
|
|
38
|
+
if (cleanedKeyword.startsWith("*")) {
|
|
39
|
+
return {
|
|
40
|
+
wildcard: {
|
|
41
|
+
[`${field}.keyword`]: {
|
|
42
|
+
value: cleanedKeyword,
|
|
43
|
+
case_insensitive: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// энгийн keyword → phrase_prefix
|
|
49
|
+
return {
|
|
50
|
+
match_phrase_prefix: {
|
|
51
|
+
[field]: cleanedKeyword,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function stringSplitter(rawString, splitter = ",") {
|
|
56
|
+
return rawString
|
|
57
|
+
.split(splitter)
|
|
58
|
+
.map((f) => f.trim())
|
|
59
|
+
.filter(Boolean);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=opensearch.parser.keyword.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.parser.keyword.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.keyword.ts"],"names":[],"mappings":";;AAEA,gDAsCC;AAxCD,2CAAmD;AAEnD,SAAgB,kBAAkB,CAChC,WAAmB,EACnB,SAMC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,wBAAgB,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAErF,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAEzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAErD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,QAAQ,KAAK,wBAAgB,CAAC,EAAE,EAAE,CAAC;gBACrC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC7B,SAAS,CAAC,oBAAoB,GAAG,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,QAAQ,KAAK,wBAAgB,CAAC,GAAG,EAAE,CAAC;gBACtC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAa,EAAE,aAAqB;IACnE,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAEpE,+BAA+B;IAC/B,IAAI,cAAc,GAAQ,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAEpE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,iEAAiE;QACjE,cAAc,IAAI,GAAG,CAAC;IACxB,CAAC;IAED,oCAAoC;IACpC,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,QAAQ,EAAE;gBACR,CAAC,GAAG,KAAK,UAAU,CAAC,EAAE;oBACpB,KAAK,EAAE,cAAc;oBACrB,gBAAgB,EAAE,IAAI;iBACvB;aACF;SACF,CAAC;IACJ,CAAC;IACD,iCAAiC;IACjC,OAAO;QACL,mBAAmB,EAAE;YACnB,CAAC,KAAK,CAAC,EAAE,cAAc;SACxB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB,EAAE,QAAQ,GAAG,GAAG;IACvD,OAAO,SAAS;SACb,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC","sourcesContent":["import { SearchOperatorOS } from \"@chinggis/types\";\n\nexport function buildSearchKeyword(\n queryParams: string,\n boolQuery: {\n must: Array<any>;\n must_not: Array<any>;\n filter: Array<any>;\n should: Array<any>;\n minimum_should_match?: number;\n },\n) {\n const params = new URLSearchParams(queryParams);\n\n const search = params.get(\"search\");\n const fieldsRaw = params.get(\"searchFields\");\n const operator = (params.get(\"searchOperator\") || SearchOperatorOS.OR).toLowerCase();\n\n if (!search || !fieldsRaw) {\n return boolQuery;\n }\n\n const fields = stringSplitter(fieldsRaw);\n\n for (const field of fields) {\n const query = buildSearchKeywordQuery(field, search);\n\n if (query) {\n if (operator === SearchOperatorOS.OR) {\n boolQuery.should.push(query);\n boolQuery.minimum_should_match = 1;\n }\n\n if (operator === SearchOperatorOS.AND) {\n boolQuery.must.push(query);\n }\n }\n }\n\n return boolQuery;\n}\n\nfunction buildSearchKeywordQuery(field: string, searchKeyword: string) {\n if (!searchKeyword || searchKeyword.trim() === \"\") return undefined;\n\n // 1. Олон *-уудыг нэг * болгох\n let cleanedKeyword: any = searchKeyword.replace(/\\*+/g, \"*\").trim();\n\n if (!cleanedKeyword.endsWith(\"*\")) {\n // 2. Хэрвээ keyword-ын төгсгөлд * байхгүй бол автоматаар * нэмэх\n cleanedKeyword += \"*\";\n }\n\n // word-д *-оор эхэлсэн бол wildcard\n if (cleanedKeyword.startsWith(\"*\")) {\n return {\n wildcard: {\n [`${field}.keyword`]: {\n value: cleanedKeyword,\n case_insensitive: true,\n },\n },\n };\n }\n // энгийн keyword → phrase_prefix\n return {\n match_phrase_prefix: {\n [field]: cleanedKeyword,\n },\n };\n}\n\nfunction stringSplitter(rawString: string, splitter = \",\") {\n return rawString\n .split(splitter)\n .map((f) => f.trim())\n .filter(Boolean);\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.boolQueryMap = void 0;
|
|
4
|
+
const types_1 = require("../../model/index.js");
|
|
5
|
+
// ---------------- Bool Query Map ----------------
|
|
6
|
+
exports.boolQueryMap = {
|
|
7
|
+
eq: (field, value) => buildTermFilter(field, value),
|
|
8
|
+
ne: (field, value) => ({ query: buildTermFilter(field, value), negation: true }),
|
|
9
|
+
in: (field, value) => buildTermsFilter(field, value),
|
|
10
|
+
gte: (field, value, existing) => buildRangeFilter(field, value, types_1.RangeTypeOS.gte, existing),
|
|
11
|
+
lte: (field, value, existing) => buildRangeFilter(field, value, types_1.RangeTypeOS.lte, existing),
|
|
12
|
+
exists: (field, value) => buildExistsFilter(field, value),
|
|
13
|
+
regex: (field, value) => buildRegexpFilter(field, value),
|
|
14
|
+
};
|
|
15
|
+
// ---------------- Operator Functions ----------------
|
|
16
|
+
function buildTermFilter(field, value) {
|
|
17
|
+
return { term: { [field]: value } };
|
|
18
|
+
}
|
|
19
|
+
function buildTermsFilter(field, value) {
|
|
20
|
+
return { terms: { [field]: value.split(",") } };
|
|
21
|
+
}
|
|
22
|
+
function buildRangeFilter(field, value, operator, existing) {
|
|
23
|
+
const val = isNaN(Number(value)) ? value : Number(value);
|
|
24
|
+
return {
|
|
25
|
+
range: {
|
|
26
|
+
[field]: {
|
|
27
|
+
...(existing?.[field] || {}),
|
|
28
|
+
[operator]: val,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function buildExistsFilter(field, value) {
|
|
34
|
+
return { query: { exists: { field } }, negation: value === "false" || value === false };
|
|
35
|
+
}
|
|
36
|
+
function buildRegexpFilter(field, value) {
|
|
37
|
+
return { regexp: { [field]: value } };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=opensearch.parser.query.map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.parser.query.map.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.query.map.ts"],"names":[],"mappings":";;;AAAA,2CAA+D;AAE/D,mDAAmD;AACtC,QAAA,YAAY,GAGrB;IACF,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;IACnD,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAChF,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC;IACpD,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,mBAAW,CAAC,GAAG,EAAE,QAAQ,CAAC;IAC1F,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,mBAAW,CAAC,GAAG,EAAE,QAAQ,CAAC;IAC1F,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC;IACzD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC;CACzD,CAAC;AAEF,uDAAuD;AACvD,SAAS,eAAe,CAAC,KAAa,EAAE,KAAa;IACnD,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa,EAAE,KAAa;IACpD,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa,EAAE,KAAa,EAAE,QAAqB,EAAE,QAA8B;IAC3G,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzD,OAAO;QACL,KAAK,EAAE;YACL,CAAC,KAAK,CAAC,EAAE;gBACP,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC5B,CAAC,QAAQ,CAAC,EAAE,GAAG;aAChB;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,KAAuB;IAC/D,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;AAC1F,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,KAAa;IACrD,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;AACxC,CAAC","sourcesContent":["import { BoolQueryTypeOS, RangeTypeOS } from \"@chinggis/types\";\n\n// ---------------- Bool Query Map ----------------\nexport const boolQueryMap: Record<\n BoolQueryTypeOS,\n (field: string, value: string, existing?: Record<string, any>) => { query: any; negation?: boolean } | any\n> = {\n eq: (field, value) => buildTermFilter(field, value),\n ne: (field, value) => ({ query: buildTermFilter(field, value), negation: true }),\n in: (field, value) => buildTermsFilter(field, value),\n gte: (field, value, existing) => buildRangeFilter(field, value, RangeTypeOS.gte, existing),\n lte: (field, value, existing) => buildRangeFilter(field, value, RangeTypeOS.lte, existing),\n exists: (field, value) => buildExistsFilter(field, value),\n regex: (field, value) => buildRegexpFilter(field, value),\n};\n\n// ---------------- Operator Functions ----------------\nfunction buildTermFilter(field: string, value: string) {\n return { term: { [field]: value } };\n}\n\nfunction buildTermsFilter(field: string, value: string) {\n return { terms: { [field]: value.split(\",\") } };\n}\n\nfunction buildRangeFilter(field: string, value: string, operator: RangeTypeOS, existing?: Record<string, any>) {\n const val = isNaN(Number(value)) ? value : Number(value);\n return {\n range: {\n [field]: {\n ...(existing?.[field] || {}),\n [operator]: val,\n },\n },\n };\n}\n\nfunction buildExistsFilter(field: string, value: string | boolean) {\n return { query: { exists: { field } }, negation: value === \"false\" || value === false };\n}\n\nfunction buildRegexpFilter(field: string, value: string) {\n return { regexp: { [field]: value } };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildSortOS(queryParams: string): any[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildSortOS = buildSortOS;
|
|
4
|
+
const types_1 = require("../../model/index.js");
|
|
5
|
+
function buildSortOS(queryParams) {
|
|
6
|
+
const params = new URLSearchParams(queryParams);
|
|
7
|
+
const fieldsRaw = params.get("sortField") || "";
|
|
8
|
+
const ordersRaw = params.get("sort") || "";
|
|
9
|
+
const fields = fieldsRaw
|
|
10
|
+
.split(",")
|
|
11
|
+
.map((f) => f.trim())
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
const orders = ordersRaw.split(",").map((o) => o.trim().toLowerCase());
|
|
14
|
+
const sort = [];
|
|
15
|
+
fields.forEach((field, i) => {
|
|
16
|
+
sort.push({
|
|
17
|
+
[field]: orders[i] || types_1.SortOrder.ASC, // default asc
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
return sort; // use directly in body.sort
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=opensearch.parser.sort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.parser.sort.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.sort.ts"],"names":[],"mappings":";;AAEA,kCAqBC;AAvBD,2CAA4C;AAE5C,SAAgB,WAAW,CAAC,WAAmB;IAC7C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;IAEhD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAE3C,MAAM,MAAM,GAAG,SAAS;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAe,CAAC,CAAC;IAEpF,MAAM,IAAI,GAAU,EAAE,CAAC;IAEvB,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,IAAI,CAAC,IAAI,CAAC;YACR,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,iBAAS,CAAC,GAAG,EAAE,cAAc;SACpD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC,CAAC,4BAA4B;AAC3C,CAAC","sourcesContent":["import { SortOrder } from \"@chinggis/types\";\n\nexport function buildSortOS(queryParams: string) {\n const params = new URLSearchParams(queryParams);\n\n const fieldsRaw = params.get(\"sortField\") || \"\";\n const ordersRaw = params.get(\"sort\") || \"\";\n\n const fields = fieldsRaw\n .split(\",\")\n .map((f) => f.trim())\n .filter(Boolean);\n const orders = ordersRaw.split(\",\").map((o) => o.trim().toLowerCase() as SortOrder);\n\n const sort: any[] = [];\n\n fields.forEach((field, i) => {\n sort.push({\n [field]: orders[i] || SortOrder.ASC, // default asc\n });\n });\n\n return sort; // use directly in body.sort\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseQueryString(queryParams: Record<string, string>): Record<string, string>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseQueryString = parseQueryString;
|
|
4
|
+
function parseQueryString(queryParams) {
|
|
5
|
+
const filtered = {};
|
|
6
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
7
|
+
if (!value)
|
|
8
|
+
continue;
|
|
9
|
+
// --- ONLY field__operator format ---
|
|
10
|
+
if (!key.includes("__"))
|
|
11
|
+
continue;
|
|
12
|
+
const parsedValue = smartParse(value);
|
|
13
|
+
filtered[key] = parsedValue;
|
|
14
|
+
}
|
|
15
|
+
return filtered;
|
|
16
|
+
}
|
|
17
|
+
function smartParse(value) {
|
|
18
|
+
if (value?.includes("*"))
|
|
19
|
+
return value;
|
|
20
|
+
// Boolean
|
|
21
|
+
if (value === "true")
|
|
22
|
+
return true;
|
|
23
|
+
if (value === "false")
|
|
24
|
+
return false;
|
|
25
|
+
// Integer
|
|
26
|
+
if (/^-?\d+$/.test(value))
|
|
27
|
+
return parseInt(value, 10);
|
|
28
|
+
// Float / Double
|
|
29
|
+
if (/^-?\d*\.\d+$/.test(value))
|
|
30
|
+
return parseFloat(value);
|
|
31
|
+
// ISO Date (YYYY-MM-DD) or Dot Date (YYYY.MM.DD)
|
|
32
|
+
if (/^\d{4}-\d{2}-\d{2}/.test(value)) {
|
|
33
|
+
const date = new Date(value);
|
|
34
|
+
if (!isNaN(date.getTime()))
|
|
35
|
+
return date;
|
|
36
|
+
}
|
|
37
|
+
if (/^\d{4}\.\d{2}\.\d{2}/.test(value)) {
|
|
38
|
+
// Convert to ISO format for Date constructor
|
|
39
|
+
const isoValue = value.replace(/\./g, "-");
|
|
40
|
+
const date = new Date(isoValue);
|
|
41
|
+
if (!isNaN(date.getTime()))
|
|
42
|
+
return date;
|
|
43
|
+
}
|
|
44
|
+
// Default: string
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=opensearch.parser.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.parser.utils.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.utils.ts"],"names":[],"mappings":";;AAAA,4CAeC;AAfD,SAAgB,gBAAgB,CAAC,WAAmC;IAClE,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAE5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,sCAAsC;QACtC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAElC,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAEtC,QAAQ,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IAC9B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,UAAU;IACV,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAEpC,UAAU;IACV,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtD,iBAAiB;IACjB,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;IAEzD,iDAAiD;IACjD,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC;IAC1C,CAAC;IACD,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC;IAC1C,CAAC;IAED,kBAAkB;IAClB,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["export function parseQueryString(queryParams: Record<string, string>): Record<string, string> {\n const filtered: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(queryParams)) {\n if (!value) continue;\n\n // --- ONLY field__operator format ---\n if (!key.includes(\"__\")) continue;\n\n const parsedValue = smartParse(value);\n\n filtered[key] = parsedValue;\n }\n\n return filtered;\n}\n\nfunction smartParse(value: string): any {\n if (value?.includes(\"*\")) return value;\n\n // Boolean\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Integer\n if (/^-?\\d+$/.test(value)) return parseInt(value, 10);\n\n // Float / Double\n if (/^-?\\d*\\.\\d+$/.test(value)) return parseFloat(value);\n\n // ISO Date (YYYY-MM-DD) or Dot Date (YYYY.MM.DD)\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) return date;\n }\n if (/^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)) {\n // Convert to ISO format for Date constructor\n const isoValue = value.replace(/\\./g, \"-\");\n const date = new Date(isoValue);\n if (!isNaN(date.getTime())) return date;\n }\n\n // Default: string\n return value;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function transformAggregationsResponse(aggs: any): any;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformAggregationsResponse = transformAggregationsResponse;
|
|
4
|
+
function transformAgg(bucket) {
|
|
5
|
+
if (!bucket)
|
|
6
|
+
return;
|
|
7
|
+
const result = {};
|
|
8
|
+
// Füge doc_count und key hinzu, falls vorhanden
|
|
9
|
+
if ("key" in bucket)
|
|
10
|
+
result.key = bucket.key;
|
|
11
|
+
if ("doc_count" in bucket)
|
|
12
|
+
result.doc_count = bucket.doc_count;
|
|
13
|
+
// Gehe alle Keys durch
|
|
14
|
+
for (const k of Object.keys(bucket)) {
|
|
15
|
+
if (k === "key" || k === "doc_count")
|
|
16
|
+
continue;
|
|
17
|
+
if (k === "value") {
|
|
18
|
+
result["value"] = bucket[k];
|
|
19
|
+
}
|
|
20
|
+
const v = bucket[k];
|
|
21
|
+
if (v && typeof v === "object") {
|
|
22
|
+
// Bucket mit Unterbuckets
|
|
23
|
+
if ("buckets" in v) {
|
|
24
|
+
result[k] = v.buckets?.map((b) => {
|
|
25
|
+
return transformAgg(b);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// Metric Aggregation (sum, avg, etc.)
|
|
29
|
+
else if ("value" in v) {
|
|
30
|
+
result[k] = v.value;
|
|
31
|
+
}
|
|
32
|
+
// Nested Objekt → rekursiv
|
|
33
|
+
else {
|
|
34
|
+
result[k] = transformAgg(v);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
// Transform für alle Top-Level Aggregationen
|
|
41
|
+
function transformAggregationsResponse(aggs) {
|
|
42
|
+
const result = {};
|
|
43
|
+
for (const key of Object.keys(aggs)) {
|
|
44
|
+
result[key] = aggs[key].buckets?.map(transformAgg) ?? transformAgg(aggs[key]);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=opensearch.transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.transform.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.transform.ts"],"names":[],"mappings":";;AAwCA,sEAMC;AA9CD,SAAS,YAAY,CAAC,MAAW;IAC/B,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,MAAM,GAAQ,EAAE,CAAC;IAEvB,gDAAgD;IAChD,IAAI,KAAK,IAAI,MAAM;QAAE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IAC7C,IAAI,WAAW,IAAI,MAAM;QAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAE/D,uBAAuB;IACvB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,WAAW;YAAE,SAAS;QAE/C,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAClB,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/B,0BAA0B;YAC1B,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBAC/B,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;gBACzB,CAAC,CAAC,CAAC;YACL,CAAC;YACD,sCAAsC;iBACjC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACtB,CAAC;YACD,2BAA2B;iBACtB,CAAC;gBACJ,MAAM,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,6CAA6C;AAC7C,SAAgB,6BAA6B,CAAC,IAAS;IACrD,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["function transformAgg(bucket: any): any {\n if (!bucket) return;\n const result: any = {};\n\n // Füge doc_count und key hinzu, falls vorhanden\n if (\"key\" in bucket) result.key = bucket.key;\n if (\"doc_count\" in bucket) result.doc_count = bucket.doc_count;\n\n // Gehe alle Keys durch\n for (const k of Object.keys(bucket)) {\n if (k === \"key\" || k === \"doc_count\") continue;\n\n if (k === \"value\") {\n result[\"value\"] = bucket[k];\n }\n\n const v = bucket[k];\n\n if (v && typeof v === \"object\") {\n // Bucket mit Unterbuckets\n if (\"buckets\" in v) {\n result[k] = v.buckets?.map((b) => {\n return transformAgg(b);\n });\n }\n // Metric Aggregation (sum, avg, etc.)\n else if (\"value\" in v) {\n result[k] = v.value;\n }\n // Nested Objekt → rekursiv\n else {\n result[k] = transformAgg(v);\n }\n }\n }\n\n return result;\n}\n\n// Transform für alle Top-Level Aggregationen\nexport function transformAggregationsResponse(aggs: any): any {\n const result: any = {};\n for (const key of Object.keys(aggs)) {\n result[key] = aggs[key].buckets?.map(transformAgg) ?? transformAgg(aggs[key]);\n }\n return result;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
interface BoolQuery {
|
|
2
|
-
must: Array<any>;
|
|
3
|
-
must_not: Array<any>;
|
|
4
|
-
filter: Array<any>;
|
|
5
|
-
should: Array<any>;
|
|
6
|
-
minimum_should_match?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare enum SearchOperator {
|
|
9
|
-
AND = "and",
|
|
10
|
-
OR = "or"
|
|
11
|
-
}
|
|
12
|
-
export declare function buildSearchQueryOS(queryParams: any, opensearchIndex: string): {
|
|
13
|
-
index: string;
|
|
14
|
-
body: {
|
|
15
|
-
query: {
|
|
16
|
-
bool: BoolQuery;
|
|
17
|
-
};
|
|
18
|
-
size: number;
|
|
19
|
-
from: number;
|
|
20
|
-
sort: any[];
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
export declare function buildSearchKeyword(queryParams: string, boolQuery: {
|
|
24
|
-
must: Array<any>;
|
|
25
|
-
must_not: Array<any>;
|
|
26
|
-
filter: Array<any>;
|
|
27
|
-
should: Array<any>;
|
|
28
|
-
minimum_should_match?: number;
|
|
29
|
-
}): {
|
|
30
|
-
must: Array<any>;
|
|
31
|
-
must_not: Array<any>;
|
|
32
|
-
filter: Array<any>;
|
|
33
|
-
should: Array<any>;
|
|
34
|
-
minimum_should_match?: number;
|
|
35
|
-
};
|
|
36
|
-
export declare function buildSortOS(queryParams: string): any[];
|
|
37
|
-
export {};
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SearchOperator = void 0;
|
|
4
|
-
exports.buildSearchQueryOS = buildSearchQueryOS;
|
|
5
|
-
exports.buildSearchKeyword = buildSearchKeyword;
|
|
6
|
-
exports.buildSortOS = buildSortOS;
|
|
7
|
-
const opensearch_utils_1 = require("./opensearch.utils");
|
|
8
|
-
var BoolQueryType;
|
|
9
|
-
(function (BoolQueryType) {
|
|
10
|
-
BoolQueryType["eq"] = "eq";
|
|
11
|
-
BoolQueryType["ne"] = "ne";
|
|
12
|
-
BoolQueryType["in"] = "in";
|
|
13
|
-
BoolQueryType["gte"] = "gte";
|
|
14
|
-
BoolQueryType["lte"] = "lte";
|
|
15
|
-
BoolQueryType["exists"] = "exists";
|
|
16
|
-
BoolQueryType["regex"] = "regex";
|
|
17
|
-
})(BoolQueryType || (BoolQueryType = {}));
|
|
18
|
-
var RangeType;
|
|
19
|
-
(function (RangeType) {
|
|
20
|
-
RangeType["lte"] = "lte";
|
|
21
|
-
RangeType["gte"] = "gte";
|
|
22
|
-
})(RangeType || (RangeType = {}));
|
|
23
|
-
var SearchOperator;
|
|
24
|
-
(function (SearchOperator) {
|
|
25
|
-
SearchOperator["AND"] = "and";
|
|
26
|
-
SearchOperator["OR"] = "or";
|
|
27
|
-
})(SearchOperator || (exports.SearchOperator = SearchOperator = {}));
|
|
28
|
-
// ---------------- Bool Query Map ----------------
|
|
29
|
-
const boolQueryMap = {
|
|
30
|
-
eq: (field, value) => buildTermFilter(field, value),
|
|
31
|
-
ne: (field, value) => ({ query: buildTermFilter(field, value), negation: true }),
|
|
32
|
-
in: (field, value) => buildTermsFilter(field, value),
|
|
33
|
-
gte: (field, value, existing) => buildRangeFilter(field, value, RangeType.gte, existing),
|
|
34
|
-
lte: (field, value, existing) => buildRangeFilter(field, value, RangeType.lte, existing),
|
|
35
|
-
exists: (field, value) => buildExistsFilter(field, value),
|
|
36
|
-
regex: (field, value) => buildRegexpFilter(field, value),
|
|
37
|
-
};
|
|
38
|
-
// ---------------- Main Function ----------------
|
|
39
|
-
function buildSearchQueryOS(queryParams, opensearchIndex) {
|
|
40
|
-
const filters = parseQueryString(queryParams);
|
|
41
|
-
const filterMap = {}; // merge range per field
|
|
42
|
-
const boolQuery = {
|
|
43
|
-
must: [],
|
|
44
|
-
must_not: [],
|
|
45
|
-
filter: [],
|
|
46
|
-
should: [],
|
|
47
|
-
minimum_should_match: undefined,
|
|
48
|
-
};
|
|
49
|
-
for (const [key, value] of Object.entries(filters)) {
|
|
50
|
-
if (!value)
|
|
51
|
-
continue;
|
|
52
|
-
const [field, boolQueryType = BoolQueryType.eq] = key.split("__");
|
|
53
|
-
const fn = boolQueryMap[boolQueryType];
|
|
54
|
-
if (!fn)
|
|
55
|
-
continue;
|
|
56
|
-
// Range filters
|
|
57
|
-
if (boolQueryType === RangeType.gte || boolQueryType === RangeType.lte) {
|
|
58
|
-
const existing = filterMap[field]?.range;
|
|
59
|
-
filterMap[field] = fn(field, value, existing);
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
// Other filters
|
|
63
|
-
const builtQuery = fn(field, value);
|
|
64
|
-
if (builtQuery.negation)
|
|
65
|
-
boolQuery.must_not.push(builtQuery.query);
|
|
66
|
-
else
|
|
67
|
-
boolQuery.must.push(builtQuery?.query ? builtQuery.query : builtQuery);
|
|
68
|
-
}
|
|
69
|
-
const filter = Object.values(filterMap);
|
|
70
|
-
if (filter.length)
|
|
71
|
-
boolQuery.filter = filter;
|
|
72
|
-
buildSearchKeyword(queryParams, boolQuery);
|
|
73
|
-
const { size, from } = (0, opensearch_utils_1.calculatePagination)(queryParams);
|
|
74
|
-
return {
|
|
75
|
-
index: opensearchIndex,
|
|
76
|
-
body: {
|
|
77
|
-
query: {
|
|
78
|
-
bool: boolQuery,
|
|
79
|
-
},
|
|
80
|
-
size: size ?? 25,
|
|
81
|
-
from: from ?? 0,
|
|
82
|
-
sort: buildSortOS(queryParams),
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
function buildSearchKeyword(queryParams, boolQuery) {
|
|
87
|
-
const params = new URLSearchParams(queryParams);
|
|
88
|
-
const search = params.get("search");
|
|
89
|
-
const fieldsRaw = params.get("searchFields");
|
|
90
|
-
const operator = (params.get("searchOperator") || SearchOperator.OR).toLowerCase();
|
|
91
|
-
if (!search || !fieldsRaw) {
|
|
92
|
-
return boolQuery;
|
|
93
|
-
}
|
|
94
|
-
const fields = stringSplitter(fieldsRaw);
|
|
95
|
-
for (const field of fields) {
|
|
96
|
-
const query = buildSearchKeywordQuery(field, search);
|
|
97
|
-
if (query) {
|
|
98
|
-
if (operator === SearchOperator.OR) {
|
|
99
|
-
boolQuery.should.push(query);
|
|
100
|
-
boolQuery.minimum_should_match = 1;
|
|
101
|
-
}
|
|
102
|
-
if (operator === SearchOperator.AND) {
|
|
103
|
-
boolQuery.must.push(query);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return boolQuery;
|
|
108
|
-
}
|
|
109
|
-
function buildSortOS(queryParams) {
|
|
110
|
-
const params = new URLSearchParams(queryParams);
|
|
111
|
-
const fieldsRaw = params.get("sortField") || "";
|
|
112
|
-
const ordersRaw = params.get("sort") || "";
|
|
113
|
-
const fields = fieldsRaw
|
|
114
|
-
.split(",")
|
|
115
|
-
.map((f) => f.trim())
|
|
116
|
-
.filter(Boolean);
|
|
117
|
-
const orders = ordersRaw.split(",").map((o) => o.trim().toLowerCase());
|
|
118
|
-
const sort = [];
|
|
119
|
-
fields.forEach((field, i) => {
|
|
120
|
-
sort.push({
|
|
121
|
-
[field]: orders[i] || "asc", // default asc
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
return sort; // use directly in body.sort
|
|
125
|
-
}
|
|
126
|
-
// ---------------- Operator Functions ----------------
|
|
127
|
-
function buildTermFilter(field, value) {
|
|
128
|
-
return { term: { [field]: value } };
|
|
129
|
-
}
|
|
130
|
-
function buildTermsFilter(field, value) {
|
|
131
|
-
return { terms: { [field]: value.split(",") } };
|
|
132
|
-
}
|
|
133
|
-
function buildRangeFilter(field, value, operator, existing) {
|
|
134
|
-
const val = isNaN(Number(value)) ? value : Number(value);
|
|
135
|
-
return {
|
|
136
|
-
range: {
|
|
137
|
-
[field]: {
|
|
138
|
-
...(existing?.[field] || {}),
|
|
139
|
-
[operator]: val,
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function buildExistsFilter(field, value) {
|
|
145
|
-
return { query: { exists: { field } }, negation: value === "false" || value === false };
|
|
146
|
-
}
|
|
147
|
-
function buildRegexpFilter(field, value) {
|
|
148
|
-
return { regexp: { [field]: value } };
|
|
149
|
-
}
|
|
150
|
-
function parseQueryString(queryParams) {
|
|
151
|
-
const filtered = {};
|
|
152
|
-
for (const [key, value] of Object.entries(queryParams)) {
|
|
153
|
-
if (!value)
|
|
154
|
-
continue;
|
|
155
|
-
// --- ONLY field__operator format ---
|
|
156
|
-
if (!key.includes("__"))
|
|
157
|
-
continue;
|
|
158
|
-
const parsedValue = smartParse(value);
|
|
159
|
-
filtered[key] = parsedValue;
|
|
160
|
-
}
|
|
161
|
-
return filtered;
|
|
162
|
-
}
|
|
163
|
-
function stringSplitter(rawString, splitter = ",") {
|
|
164
|
-
return rawString
|
|
165
|
-
.split(splitter)
|
|
166
|
-
.map((f) => f.trim())
|
|
167
|
-
.filter(Boolean);
|
|
168
|
-
}
|
|
169
|
-
function buildSearchKeywordQuery(field, searchKeyword) {
|
|
170
|
-
if (!searchKeyword || searchKeyword.trim() === "")
|
|
171
|
-
return undefined;
|
|
172
|
-
// 1. Олон *-уудыг нэг * болгох
|
|
173
|
-
let cleanedKeyword = searchKeyword.replace(/\*+/g, "*").trim();
|
|
174
|
-
if (!cleanedKeyword.endsWith("*")) {
|
|
175
|
-
// 2. Хэрвээ keyword-ын төгсгөлд * байхгүй бол автоматаар * нэмэх
|
|
176
|
-
cleanedKeyword += "*";
|
|
177
|
-
}
|
|
178
|
-
// word-д *-оор эхэлсэн бол wildcard
|
|
179
|
-
if (cleanedKeyword.startsWith("*")) {
|
|
180
|
-
return {
|
|
181
|
-
wildcard: {
|
|
182
|
-
[`${field}.keyword`]: {
|
|
183
|
-
value: cleanedKeyword,
|
|
184
|
-
case_insensitive: true,
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
// энгийн keyword → phrase_prefix
|
|
190
|
-
return {
|
|
191
|
-
match_phrase_prefix: {
|
|
192
|
-
[field]: cleanedKeyword,
|
|
193
|
-
},
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
function smartParse(value) {
|
|
197
|
-
if (value?.includes("*"))
|
|
198
|
-
return value;
|
|
199
|
-
// Boolean
|
|
200
|
-
if (value === "true")
|
|
201
|
-
return true;
|
|
202
|
-
if (value === "false")
|
|
203
|
-
return false;
|
|
204
|
-
// Integer
|
|
205
|
-
if (/^-?\d+$/.test(value))
|
|
206
|
-
return parseInt(value, 10);
|
|
207
|
-
// Float / Double
|
|
208
|
-
if (/^-?\d*\.\d+$/.test(value))
|
|
209
|
-
return parseFloat(value);
|
|
210
|
-
// ISO Date (YYYY-MM-DD) or Dot Date (YYYY.MM.DD)
|
|
211
|
-
if (/^\d{4}-\d{2}-\d{2}/.test(value)) {
|
|
212
|
-
const date = new Date(value);
|
|
213
|
-
if (!isNaN(date.getTime()))
|
|
214
|
-
return date;
|
|
215
|
-
}
|
|
216
|
-
if (/^\d{4}\.\d{2}\.\d{2}/.test(value)) {
|
|
217
|
-
// Convert to ISO format for Date constructor
|
|
218
|
-
const isoValue = value.replace(/\./g, "-");
|
|
219
|
-
const date = new Date(isoValue);
|
|
220
|
-
if (!isNaN(date.getTime()))
|
|
221
|
-
return date;
|
|
222
|
-
}
|
|
223
|
-
// Default: string
|
|
224
|
-
return value;
|
|
225
|
-
}
|
|
226
|
-
//# sourceMappingURL=opensearch.parser.js.map
|