@webiny/api-headless-cms-ddb-es 5.34.3 → 5.34.4
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/operations/entry/elasticsearch/body.js +2 -0
- package/operations/entry/elasticsearch/body.js.map +1 -1
- package/operations/entry/elasticsearch/fullTextSearch.d.ts +4 -1
- package/operations/entry/elasticsearch/fullTextSearch.js +78 -10
- package/operations/entry/elasticsearch/fullTextSearch.js.map +1 -1
- package/operations/entry/elasticsearch/fullTextSearchFields.js +8 -29
- package/operations/entry/elasticsearch/fullTextSearchFields.js.map +1 -1
- package/package.json +14 -14
- package/plugins/CmsEntryElasticsearchFullTextSearchPlugin.d.ts +23 -0
- package/plugins/CmsEntryElasticsearchFullTextSearchPlugin.js +38 -0
- package/plugins/CmsEntryElasticsearchFullTextSearchPlugin.js.map +1 -0
- package/plugins/index.d.ts +1 -0
- package/plugins/index.js +13 -0
- package/plugins/index.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createElasticsearchBody","plugins","model","params","fields","search","term","where","sort","initialSort","after","limit","modelFields","createModelFields","queryModifierPlugins","createQueryModifierPluginList","sortModifierPlugins","createSortModifierPluginList","bodyModifierPlugins","createBodyModifierPluginList","fullTextSearchFields","createFullTextSearchFields","query","createInitialQuery","applyFullTextSearch","execFiltering","createExecFiltering","pl","modifyQuery","createElasticsearchSort","modifySort","boolQuery","must","length","undefined","must_not","should","filter","assignMinimumShouldMatchToQuery","body","bool","size","search_after","track_total_hits","modifyBody"],"sources":["body.ts"],"sourcesContent":["import { PluginsContainer } from \"@webiny/plugins\";\nimport { CmsEntryListParams, CmsEntryListWhere, CmsModel } from \"@webiny/api-headless-cms/types\";\nimport { createModelFields } from \"./fields\";\nimport { createFullTextSearchFields } from \"./fullTextSearchFields\";\nimport { createInitialQuery } from \"./initialQuery\";\nimport { applyFullTextSearch } from \"./fullTextSearch\";\nimport { createQueryModifierPluginList } from \"./plugins/queryModifier\";\nimport { createSortModifierPluginList } from \"./plugins/sortModifier\";\nimport { createBodyModifierPluginList } from \"./plugins/bodyModifier\";\nimport { createElasticsearchSort } from \"./sort\";\nimport { PrimitiveValue, SearchBody, BoolQueryConfig } from \"@webiny/api-elasticsearch/types\";\nimport { createExecFiltering } from \"./filtering\";\nimport { assignMinimumShouldMatchToQuery } from \"./assignMinimumShouldMatchToQuery\";\n\ninterface Params {\n plugins: PluginsContainer;\n model: CmsModel;\n params: Omit<CmsEntryListParams, \"where\" | \"after\"> & {\n where: CmsEntryListWhere;\n after?: PrimitiveValue[];\n };\n}\nexport const createElasticsearchBody = ({ plugins, model, params }: Params): SearchBody => {\n const { fields, search: term, where, sort: initialSort, after, limit } = params;\n /**\n * We need the model fields constructed as a key -> field value, so we do not need to iterate through array when we require some field.\n */\n const modelFields = createModelFields({\n plugins,\n fields: model.fields\n });\n\n /**\n * We need the query modifier plugins.\n */\n const queryModifierPlugins = createQueryModifierPluginList({\n plugins,\n model\n });\n /**\n * We need the sort modifier plugins.\n */\n const sortModifierPlugins = createSortModifierPluginList({\n plugins,\n model\n });\n /**\n * We need the body modifier plugins.\n */\n const bodyModifierPlugins = createBodyModifierPluginList({\n plugins,\n model\n });\n /**\n * We need the fields which we can search through via the full text search.\n *\n */\n const fullTextSearchFields = createFullTextSearchFields({\n model,\n term,\n fields\n });\n /**\n * The initial elasticsearch query where we attach some default conditions we always need.\n */\n const query = createInitialQuery({\n where,\n model\n });\n /**\n * Apply the full text search, if term is set.\n */\n applyFullTextSearch({\n query,\n term,\n fields: fullTextSearchFields\n });\n\n const execFiltering = createExecFiltering({\n model,\n fields: modelFields,\n plugins\n });\n\n execFiltering({\n where,\n query\n });\n\n for (const pl of queryModifierPlugins) {\n pl.modifyQuery({ query, model, where });\n }\n\n const sort = createElasticsearchSort({\n plugins,\n sort: initialSort,\n modelFields,\n model\n });\n\n for (const pl of sortModifierPlugins) {\n pl.modifySort({\n sort,\n model\n });\n }\n\n const boolQuery: BoolQueryConfig = {\n must: query.must.length > 0 ? query.must : undefined,\n must_not: query.must_not.length > 0 ? query.must_not : undefined,\n should: query.should.length > 0 ? query.should : undefined,\n filter: query.filter.length > 0 ? query.filter : undefined\n };\n\n assignMinimumShouldMatchToQuery({\n query: boolQuery\n });\n\n const body: SearchBody = {\n query: {\n bool: boolQuery\n },\n sort,\n size: (limit || 0) + 1,\n search_after: after,\n track_total_hits: true\n };\n\n for (const pl of bodyModifierPlugins) {\n pl.modifyBody({\n body,\n model,\n where\n });\n }\n\n return body;\n};\n"],"mappings":";;;;;;;AAEA;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;AAEA;;AACA;;AAUO,MAAMA,uBAAuB,GAAG,CAAC;EAAEC,OAAF;EAAWC,KAAX;EAAkBC;AAAlB,CAAD,KAAoD;EACvF,MAAM;IAAEC,MAAF;IAAUC,MAAM,EAAEC,IAAlB;IAAwBC,KAAxB;IAA+BC,IAAI,EAAEC,WAArC;IAAkDC,KAAlD;IAAyDC;EAAzD,IAAmER,MAAzE;EACA;AACJ;AACA;;EACI,MAAMS,WAAW,GAAG,IAAAC,yBAAA,EAAkB;IAClCZ,OADkC;IAElCG,MAAM,EAAEF,KAAK,CAACE;EAFoB,CAAlB,CAApB;EAKA;AACJ;AACA;;EACI,MAAMU,oBAAoB,GAAG,IAAAC,4CAAA,EAA8B;IACvDd,OADuD;IAEvDC;EAFuD,CAA9B,CAA7B;EAIA;AACJ;AACA;;EACI,MAAMc,mBAAmB,GAAG,IAAAC,0CAAA,EAA6B;IACrDhB,OADqD;IAErDC;EAFqD,CAA7B,CAA5B;EAIA;AACJ;AACA;;EACI,MAAMgB,mBAAmB,GAAG,IAAAC,0CAAA,EAA6B;IACrDlB,OADqD;IAErDC;EAFqD,CAA7B,CAA5B;EAIA;AACJ;AACA;AACA;;EACI,MAAMkB,oBAAoB,GAAG,IAAAC,gDAAA,EAA2B;IACpDnB,KADoD;IAEpDI,IAFoD;IAGpDF;EAHoD,CAA3B,CAA7B;EAKA;AACJ;AACA;;EACI,MAAMkB,KAAK,GAAG,IAAAC,gCAAA,EAAmB;IAC7BhB,KAD6B;IAE7BL;EAF6B,CAAnB,CAAd;EAIA;AACJ;AACA;;EACI,IAAAsB,mCAAA,EAAoB;
|
|
1
|
+
{"version":3,"names":["createElasticsearchBody","plugins","model","params","fields","search","term","where","sort","initialSort","after","limit","modelFields","createModelFields","queryModifierPlugins","createQueryModifierPluginList","sortModifierPlugins","createSortModifierPluginList","bodyModifierPlugins","createBodyModifierPluginList","fullTextSearchFields","createFullTextSearchFields","query","createInitialQuery","applyFullTextSearch","execFiltering","createExecFiltering","pl","modifyQuery","createElasticsearchSort","modifySort","boolQuery","must","length","undefined","must_not","should","filter","assignMinimumShouldMatchToQuery","body","bool","size","search_after","track_total_hits","modifyBody"],"sources":["body.ts"],"sourcesContent":["import { PluginsContainer } from \"@webiny/plugins\";\nimport { CmsEntryListParams, CmsEntryListWhere, CmsModel } from \"@webiny/api-headless-cms/types\";\nimport { createModelFields } from \"./fields\";\nimport { createFullTextSearchFields } from \"./fullTextSearchFields\";\nimport { createInitialQuery } from \"./initialQuery\";\nimport { applyFullTextSearch } from \"./fullTextSearch\";\nimport { createQueryModifierPluginList } from \"./plugins/queryModifier\";\nimport { createSortModifierPluginList } from \"./plugins/sortModifier\";\nimport { createBodyModifierPluginList } from \"./plugins/bodyModifier\";\nimport { createElasticsearchSort } from \"./sort\";\nimport { PrimitiveValue, SearchBody, BoolQueryConfig } from \"@webiny/api-elasticsearch/types\";\nimport { createExecFiltering } from \"./filtering\";\nimport { assignMinimumShouldMatchToQuery } from \"./assignMinimumShouldMatchToQuery\";\n\ninterface Params {\n plugins: PluginsContainer;\n model: CmsModel;\n params: Omit<CmsEntryListParams, \"where\" | \"after\"> & {\n where: CmsEntryListWhere;\n after?: PrimitiveValue[];\n };\n}\nexport const createElasticsearchBody = ({ plugins, model, params }: Params): SearchBody => {\n const { fields, search: term, where, sort: initialSort, after, limit } = params;\n /**\n * We need the model fields constructed as a key -> field value, so we do not need to iterate through array when we require some field.\n */\n const modelFields = createModelFields({\n plugins,\n fields: model.fields\n });\n\n /**\n * We need the query modifier plugins.\n */\n const queryModifierPlugins = createQueryModifierPluginList({\n plugins,\n model\n });\n /**\n * We need the sort modifier plugins.\n */\n const sortModifierPlugins = createSortModifierPluginList({\n plugins,\n model\n });\n /**\n * We need the body modifier plugins.\n */\n const bodyModifierPlugins = createBodyModifierPluginList({\n plugins,\n model\n });\n /**\n * We need the fields which we can search through via the full text search.\n *\n */\n const fullTextSearchFields = createFullTextSearchFields({\n model,\n term,\n fields\n });\n /**\n * The initial elasticsearch query where we attach some default conditions we always need.\n */\n const query = createInitialQuery({\n where,\n model\n });\n /**\n * Apply the full text search, if term is set.\n */\n applyFullTextSearch({\n model,\n plugins,\n query,\n term,\n fields: fullTextSearchFields\n });\n\n const execFiltering = createExecFiltering({\n model,\n fields: modelFields,\n plugins\n });\n\n execFiltering({\n where,\n query\n });\n\n for (const pl of queryModifierPlugins) {\n pl.modifyQuery({ query, model, where });\n }\n\n const sort = createElasticsearchSort({\n plugins,\n sort: initialSort,\n modelFields,\n model\n });\n\n for (const pl of sortModifierPlugins) {\n pl.modifySort({\n sort,\n model\n });\n }\n\n const boolQuery: BoolQueryConfig = {\n must: query.must.length > 0 ? query.must : undefined,\n must_not: query.must_not.length > 0 ? query.must_not : undefined,\n should: query.should.length > 0 ? query.should : undefined,\n filter: query.filter.length > 0 ? query.filter : undefined\n };\n\n assignMinimumShouldMatchToQuery({\n query: boolQuery\n });\n\n const body: SearchBody = {\n query: {\n bool: boolQuery\n },\n sort,\n size: (limit || 0) + 1,\n search_after: after,\n track_total_hits: true\n };\n\n for (const pl of bodyModifierPlugins) {\n pl.modifyBody({\n body,\n model,\n where\n });\n }\n\n return body;\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ElasticsearchBoolQueryConfig } from "@webiny/api-elasticsearch/types";
|
|
2
|
-
import { CmsModelField } from "@webiny/api-headless-cms/types";
|
|
2
|
+
import { CmsModel, CmsModelField } from "@webiny/api-headless-cms/types";
|
|
3
|
+
import { PluginsContainer } from "@webiny/plugins";
|
|
3
4
|
interface Params {
|
|
5
|
+
plugins: PluginsContainer;
|
|
6
|
+
model: CmsModel;
|
|
4
7
|
query: ElasticsearchBoolQueryConfig;
|
|
5
8
|
term?: string;
|
|
6
9
|
fields: CmsModelField[];
|
|
@@ -7,27 +7,95 @@ exports.applyFullTextSearch = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _apiElasticsearch = require("@webiny/api-elasticsearch");
|
|
9
9
|
|
|
10
|
+
var _plugins = require("../../../plugins");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Our default plugin is working with the AND operator for the multiple words query string.
|
|
14
|
+
*/
|
|
15
|
+
const defaultPlugin = (0, _plugins.createCmsEntryElasticsearchFullTextSearchPlugin)({
|
|
16
|
+
apply: params => {
|
|
17
|
+
const {
|
|
18
|
+
query,
|
|
19
|
+
term,
|
|
20
|
+
fields,
|
|
21
|
+
createFieldPath,
|
|
22
|
+
prepareTerm
|
|
23
|
+
} = params;
|
|
24
|
+
query.must.push({
|
|
25
|
+
query_string: {
|
|
26
|
+
allow_leading_wildcard: true,
|
|
27
|
+
fields: fields.map(createFieldPath),
|
|
28
|
+
query: `*${prepareTerm(term)}*`,
|
|
29
|
+
default_operator: "and"
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
defaultPlugin.name = "headless-cms.elasticsearch.entry.fullTextSearch.default";
|
|
35
|
+
|
|
36
|
+
const getPlugin = params => {
|
|
37
|
+
const {
|
|
38
|
+
container,
|
|
39
|
+
model
|
|
40
|
+
} = params;
|
|
41
|
+
/**
|
|
42
|
+
* We need to reverse the plugins, so we can take the last one first - possibility to override existing plugins.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
const plugins = container.byType(_plugins.CmsEntryElasticsearchFullTextSearchPlugin.type).reverse();
|
|
46
|
+
/**
|
|
47
|
+
* We need to find the most specific plugin for the given model.
|
|
48
|
+
* Also, we need to use the first possible plugin if the specific one is not found.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
let plugin = null;
|
|
52
|
+
|
|
53
|
+
for (const pl of plugins) {
|
|
54
|
+
const models = pl.models || [];
|
|
55
|
+
/**
|
|
56
|
+
* We take the first available plugin for the given model.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
if (models.includes(model.modelId)) {
|
|
60
|
+
return pl;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Then we set the first possible plugin, which has no models defined, as the default one.
|
|
64
|
+
* It is important not to set the plugin which has models defined as they are specifically for the targeted model.
|
|
65
|
+
*/
|
|
66
|
+
//
|
|
67
|
+
else if (!plugin && models.length === 0) {
|
|
68
|
+
plugin = pl;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return plugin || defaultPlugin;
|
|
73
|
+
};
|
|
74
|
+
|
|
10
75
|
const applyFullTextSearch = params => {
|
|
11
76
|
const {
|
|
77
|
+
plugins,
|
|
12
78
|
query,
|
|
13
79
|
term,
|
|
14
|
-
fields
|
|
80
|
+
fields,
|
|
81
|
+
model
|
|
15
82
|
} = params;
|
|
16
83
|
|
|
17
84
|
if (!term || term.length === 0 || fields.length === 0) {
|
|
18
85
|
return;
|
|
19
86
|
}
|
|
20
87
|
|
|
21
|
-
const
|
|
22
|
-
|
|
88
|
+
const plugin = getPlugin({
|
|
89
|
+
container: plugins,
|
|
90
|
+
model
|
|
23
91
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
92
|
+
plugin.apply({
|
|
93
|
+
model,
|
|
94
|
+
createFieldPath: field => `values.${field.storageId}`,
|
|
95
|
+
fields,
|
|
96
|
+
query,
|
|
97
|
+
term,
|
|
98
|
+
prepareTerm: _apiElasticsearch.normalizeValue
|
|
31
99
|
});
|
|
32
100
|
};
|
|
33
101
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["defaultPlugin","createCmsEntryElasticsearchFullTextSearchPlugin","apply","params","query","term","fields","createFieldPath","prepareTerm","must","push","query_string","allow_leading_wildcard","map","default_operator","name","getPlugin","container","model","plugins","byType","CmsEntryElasticsearchFullTextSearchPlugin","type","reverse","plugin","pl","models","includes","modelId","length","applyFullTextSearch","field","storageId","normalizeValue"],"sources":["fullTextSearch.ts"],"sourcesContent":["import { ElasticsearchBoolQueryConfig } from \"@webiny/api-elasticsearch/types\";\nimport { normalizeValue } from \"@webiny/api-elasticsearch\";\nimport { CmsModel, CmsModelField } from \"@webiny/api-headless-cms/types\";\nimport { PluginsContainer } from \"@webiny/plugins\";\nimport {\n CmsEntryElasticsearchFullTextSearchPlugin,\n createCmsEntryElasticsearchFullTextSearchPlugin\n} from \"~/plugins\";\n\n/**\n * Our default plugin is working with the AND operator for the multiple words query string.\n */\nconst defaultPlugin = createCmsEntryElasticsearchFullTextSearchPlugin({\n apply: params => {\n const { query, term, fields, createFieldPath, prepareTerm } = params;\n\n query.must.push({\n query_string: {\n allow_leading_wildcard: true,\n fields: fields.map(createFieldPath),\n query: `*${prepareTerm(term)}*`,\n default_operator: \"and\"\n }\n });\n }\n});\ndefaultPlugin.name = \"headless-cms.elasticsearch.entry.fullTextSearch.default\";\n\ninterface GetPluginParams {\n container: PluginsContainer;\n model: CmsModel;\n}\nconst getPlugin = (params: GetPluginParams): CmsEntryElasticsearchFullTextSearchPlugin => {\n const { container, model } = params;\n /**\n * We need to reverse the plugins, so we can take the last one first - possibility to override existing plugins.\n */\n const plugins = container\n .byType<CmsEntryElasticsearchFullTextSearchPlugin>(\n CmsEntryElasticsearchFullTextSearchPlugin.type\n )\n .reverse();\n /**\n * We need to find the most specific plugin for the given model.\n * Also, we need to use the first possible plugin if the specific one is not found.\n */\n let plugin: CmsEntryElasticsearchFullTextSearchPlugin | null = null;\n for (const pl of plugins) {\n const models = pl.models || [];\n /**\n * We take the first available plugin for the given model.\n */\n if (models.includes(model.modelId)) {\n return pl;\n }\n /**\n * Then we set the first possible plugin, which has no models defined, as the default one.\n * It is important not to set the plugin which has models defined as they are specifically for the targeted model.\n */\n //\n else if (!plugin && models.length === 0) {\n plugin = pl;\n }\n }\n\n return plugin || defaultPlugin;\n};\n\ninterface Params {\n plugins: PluginsContainer;\n model: CmsModel;\n query: ElasticsearchBoolQueryConfig;\n term?: string;\n fields: CmsModelField[];\n}\nexport const applyFullTextSearch = (params: Params): void => {\n const { plugins, query, term, fields, model } = params;\n if (!term || term.length === 0 || fields.length === 0) {\n return;\n }\n\n const plugin = getPlugin({\n container: plugins,\n model\n });\n\n plugin.apply({\n model,\n createFieldPath: field => `values.${field.storageId}`,\n fields,\n query,\n term,\n prepareTerm: normalizeValue\n });\n};\n"],"mappings":";;;;;;;AACA;;AAGA;;AAKA;AACA;AACA;AACA,MAAMA,aAAa,GAAG,IAAAC,wDAAA,EAAgD;EAClEC,KAAK,EAAEC,MAAM,IAAI;IACb,MAAM;MAAEC,KAAF;MAASC,IAAT;MAAeC,MAAf;MAAuBC,eAAvB;MAAwCC;IAAxC,IAAwDL,MAA9D;IAEAC,KAAK,CAACK,IAAN,CAAWC,IAAX,CAAgB;MACZC,YAAY,EAAE;QACVC,sBAAsB,EAAE,IADd;QAEVN,MAAM,EAAEA,MAAM,CAACO,GAAP,CAAWN,eAAX,CAFE;QAGVH,KAAK,EAAG,IAAGI,WAAW,CAACH,IAAD,CAAO,GAHnB;QAIVS,gBAAgB,EAAE;MAJR;IADF,CAAhB;EAQH;AAZiE,CAAhD,CAAtB;AAcAd,aAAa,CAACe,IAAd,GAAqB,yDAArB;;AAMA,MAAMC,SAAS,GAAIb,MAAD,IAAwE;EACtF,MAAM;IAAEc,SAAF;IAAaC;EAAb,IAAuBf,MAA7B;EACA;AACJ;AACA;;EACI,MAAMgB,OAAO,GAAGF,SAAS,CACpBG,MADW,CAERC,kDAAA,CAA0CC,IAFlC,EAIXC,OAJW,EAAhB;EAKA;AACJ;AACA;AACA;;EACI,IAAIC,MAAwD,GAAG,IAA/D;;EACA,KAAK,MAAMC,EAAX,IAAiBN,OAAjB,EAA0B;IACtB,MAAMO,MAAM,GAAGD,EAAE,CAACC,MAAH,IAAa,EAA5B;IACA;AACR;AACA;;IACQ,IAAIA,MAAM,CAACC,QAAP,CAAgBT,KAAK,CAACU,OAAtB,CAAJ,EAAoC;MAChC,OAAOH,EAAP;IACH;IACD;AACR;AACA;AACA;IACQ;IAPA,KAQK,IAAI,CAACD,MAAD,IAAWE,MAAM,CAACG,MAAP,KAAkB,CAAjC,EAAoC;MACrCL,MAAM,GAAGC,EAAT;IACH;EACJ;;EAED,OAAOD,MAAM,IAAIxB,aAAjB;AACH,CAlCD;;AA2CO,MAAM8B,mBAAmB,GAAI3B,MAAD,IAA0B;EACzD,MAAM;IAAEgB,OAAF;IAAWf,KAAX;IAAkBC,IAAlB;IAAwBC,MAAxB;IAAgCY;EAAhC,IAA0Cf,MAAhD;;EACA,IAAI,CAACE,IAAD,IAASA,IAAI,CAACwB,MAAL,KAAgB,CAAzB,IAA8BvB,MAAM,CAACuB,MAAP,KAAkB,CAApD,EAAuD;IACnD;EACH;;EAED,MAAML,MAAM,GAAGR,SAAS,CAAC;IACrBC,SAAS,EAAEE,OADU;IAErBD;EAFqB,CAAD,CAAxB;EAKAM,MAAM,CAACtB,KAAP,CAAa;IACTgB,KADS;IAETX,eAAe,EAAEwB,KAAK,IAAK,UAASA,KAAK,CAACC,SAAU,EAF3C;IAGT1B,MAHS;IAITF,KAJS;IAKTC,IALS;IAMTG,WAAW,EAAEyB;EANJ,CAAb;AAQH,CAnBM"}
|
|
@@ -5,19 +5,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.createFullTextSearchFields = void 0;
|
|
7
7
|
|
|
8
|
-
/* eslint-disable */
|
|
9
|
-
const extractFields = fields => {
|
|
10
|
-
return fields.reduce((collection, field) => {
|
|
11
|
-
var _field$settings;
|
|
12
|
-
|
|
13
|
-
if ((_field$settings = field.settings) !== null && _field$settings !== void 0 && _field$settings.fields) {
|
|
14
|
-
collection.push(...extractFields(field.settings.fields));
|
|
15
|
-
} else if (field) {}
|
|
16
|
-
|
|
17
|
-
return collection;
|
|
18
|
-
}, []);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
8
|
const createFullTextSearchFields = params => {
|
|
22
9
|
const {
|
|
23
10
|
term,
|
|
@@ -25,28 +12,20 @@ const createFullTextSearchFields = params => {
|
|
|
25
12
|
fields
|
|
26
13
|
} = params;
|
|
27
14
|
|
|
28
|
-
if (!fields || fields.length === 0 || !term || term.length === 0) {
|
|
15
|
+
if (!fields || fields.length === 0 || !term || term.trim().length === 0) {
|
|
29
16
|
return [];
|
|
30
17
|
}
|
|
31
18
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* No point in going through fields if there is no search performed - no search term.
|
|
35
|
-
*/
|
|
19
|
+
return fields.reduce((collection, fieldId) => {
|
|
20
|
+
const field = model.fields.find(f => f.fieldId === fieldId);
|
|
36
21
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const field = model.fields.find(f => f.fieldId === fieldId);
|
|
40
|
-
|
|
41
|
-
if (!field) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
fullTextSearchFields.push(field);
|
|
22
|
+
if (!field) {
|
|
23
|
+
return collection;
|
|
46
24
|
}
|
|
47
|
-
}
|
|
48
25
|
|
|
49
|
-
|
|
26
|
+
collection.push(field);
|
|
27
|
+
return collection;
|
|
28
|
+
}, []);
|
|
50
29
|
};
|
|
51
30
|
|
|
52
31
|
exports.createFullTextSearchFields = createFullTextSearchFields;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["createFullTextSearchFields","params","term","model","fields","length","trim","reduce","collection","fieldId","field","find","f","push"],"sources":["fullTextSearchFields.ts"],"sourcesContent":["import { CmsModel, CmsModelField } from \"@webiny/api-headless-cms/types\";\n\ninterface Params {\n model: CmsModel;\n term?: string;\n fields?: string[];\n}\nexport const createFullTextSearchFields = (params: Params): CmsModelField[] => {\n const { term, model, fields } = params;\n if (!fields || fields.length === 0 || !term || term.trim().length === 0) {\n return [];\n }\n return fields.reduce<CmsModelField[]>((collection, fieldId) => {\n const field = model.fields.find(f => f.fieldId === fieldId);\n if (!field) {\n return collection;\n }\n collection.push(field);\n return collection;\n }, []);\n};\n"],"mappings":";;;;;;;AAOO,MAAMA,0BAA0B,GAAIC,MAAD,IAAqC;EAC3E,MAAM;IAAEC,IAAF;IAAQC,KAAR;IAAeC;EAAf,IAA0BH,MAAhC;;EACA,IAAI,CAACG,MAAD,IAAWA,MAAM,CAACC,MAAP,KAAkB,CAA7B,IAAkC,CAACH,IAAnC,IAA2CA,IAAI,CAACI,IAAL,GAAYD,MAAZ,KAAuB,CAAtE,EAAyE;IACrE,OAAO,EAAP;EACH;;EACD,OAAOD,MAAM,CAACG,MAAP,CAA+B,CAACC,UAAD,EAAaC,OAAb,KAAyB;IAC3D,MAAMC,KAAK,GAAGP,KAAK,CAACC,MAAN,CAAaO,IAAb,CAAkBC,CAAC,IAAIA,CAAC,CAACH,OAAF,KAAcA,OAArC,CAAd;;IACA,IAAI,CAACC,KAAL,EAAY;MACR,OAAOF,UAAP;IACH;;IACDA,UAAU,CAACK,IAAX,CAAgBH,KAAhB;IACA,OAAOF,UAAP;EACH,CAPM,EAOJ,EAPI,CAAP;AAQH,CAbM"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/api-headless-cms-ddb-es",
|
|
3
|
-
"version": "5.34.
|
|
3
|
+
"version": "5.34.4",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"@webiny/api-headless-cms",
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@babel/runtime": "7.19.0",
|
|
26
|
-
"@webiny/api": "5.34.
|
|
27
|
-
"@webiny/api-elasticsearch": "5.34.
|
|
28
|
-
"@webiny/api-headless-cms": "5.34.
|
|
29
|
-
"@webiny/db-dynamodb": "5.34.
|
|
30
|
-
"@webiny/error": "5.34.
|
|
31
|
-
"@webiny/handler-db": "5.34.
|
|
32
|
-
"@webiny/plugins": "5.34.
|
|
33
|
-
"@webiny/utils": "5.34.
|
|
26
|
+
"@webiny/api": "5.34.4",
|
|
27
|
+
"@webiny/api-elasticsearch": "5.34.4",
|
|
28
|
+
"@webiny/api-headless-cms": "5.34.4",
|
|
29
|
+
"@webiny/db-dynamodb": "5.34.4",
|
|
30
|
+
"@webiny/error": "5.34.4",
|
|
31
|
+
"@webiny/handler-db": "5.34.4",
|
|
32
|
+
"@webiny/plugins": "5.34.4",
|
|
33
|
+
"@webiny/utils": "5.34.4",
|
|
34
34
|
"dataloader": "2.1.0",
|
|
35
35
|
"dynamodb-toolbox": "0.3.5",
|
|
36
36
|
"jsonpack": "1.1.5",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"@babel/preset-env": "^7.19.4",
|
|
43
43
|
"@elastic/elasticsearch": "7.12.0",
|
|
44
44
|
"@types/jsonpack": "^1.1.0",
|
|
45
|
-
"@webiny/api-dynamodb-to-elasticsearch": "^5.34.
|
|
46
|
-
"@webiny/cli": "^5.34.
|
|
47
|
-
"@webiny/handler-aws": "^5.34.
|
|
48
|
-
"@webiny/project-utils": "^5.34.
|
|
45
|
+
"@webiny/api-dynamodb-to-elasticsearch": "^5.34.4",
|
|
46
|
+
"@webiny/cli": "^5.34.4",
|
|
47
|
+
"@webiny/handler-aws": "^5.34.4",
|
|
48
|
+
"@webiny/project-utils": "^5.34.4",
|
|
49
49
|
"jest": "^28.1.0",
|
|
50
50
|
"jest-dynalite": "^3.2.0",
|
|
51
51
|
"jest-environment-node": "^27.2.4",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"build": "yarn webiny run build",
|
|
65
65
|
"watch": "yarn webiny run watch"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "e5e63a5a02def63eeded2c8f61beb7f0b3744c01"
|
|
68
68
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Plugin } from "@webiny/plugins";
|
|
2
|
+
import { ElasticsearchBoolQueryConfig } from "@webiny/api-elasticsearch/types";
|
|
3
|
+
import { CmsModel, CmsModelField } from "@webiny/api-headless-cms/types";
|
|
4
|
+
export interface CmsEntryElasticsearchFullTextSearchPluginCbParams {
|
|
5
|
+
model: CmsModel;
|
|
6
|
+
query: ElasticsearchBoolQueryConfig;
|
|
7
|
+
term: string;
|
|
8
|
+
fields: CmsModelField[];
|
|
9
|
+
createFieldPath: (field: CmsModelField) => string;
|
|
10
|
+
prepareTerm: (term: string) => string;
|
|
11
|
+
}
|
|
12
|
+
export interface CmsEntryElasticsearchFullTextSearchPluginParams {
|
|
13
|
+
models?: string[];
|
|
14
|
+
apply: (params: CmsEntryElasticsearchFullTextSearchPluginCbParams) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare class CmsEntryElasticsearchFullTextSearchPlugin extends Plugin {
|
|
17
|
+
static readonly type: string;
|
|
18
|
+
private readonly params;
|
|
19
|
+
get models(): string[] | undefined;
|
|
20
|
+
constructor(params: CmsEntryElasticsearchFullTextSearchPluginParams);
|
|
21
|
+
apply(params: CmsEntryElasticsearchFullTextSearchPluginCbParams): void;
|
|
22
|
+
}
|
|
23
|
+
export declare const createCmsEntryElasticsearchFullTextSearchPlugin: (params: CmsEntryElasticsearchFullTextSearchPluginParams) => CmsEntryElasticsearchFullTextSearchPlugin;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.createCmsEntryElasticsearchFullTextSearchPlugin = exports.CmsEntryElasticsearchFullTextSearchPlugin = void 0;
|
|
9
|
+
|
|
10
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
|
|
12
|
+
var _plugins = require("@webiny/plugins");
|
|
13
|
+
|
|
14
|
+
class CmsEntryElasticsearchFullTextSearchPlugin extends _plugins.Plugin {
|
|
15
|
+
get models() {
|
|
16
|
+
return this.params.models;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor(params) {
|
|
20
|
+
super();
|
|
21
|
+
(0, _defineProperty2.default)(this, "params", void 0);
|
|
22
|
+
this.params = params;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
apply(params) {
|
|
26
|
+
return this.params.apply(params);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
exports.CmsEntryElasticsearchFullTextSearchPlugin = CmsEntryElasticsearchFullTextSearchPlugin;
|
|
32
|
+
(0, _defineProperty2.default)(CmsEntryElasticsearchFullTextSearchPlugin, "type", "headless-cms.elasticsearch.entry.fullTextSearch");
|
|
33
|
+
|
|
34
|
+
const createCmsEntryElasticsearchFullTextSearchPlugin = params => {
|
|
35
|
+
return new CmsEntryElasticsearchFullTextSearchPlugin(params);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
exports.createCmsEntryElasticsearchFullTextSearchPlugin = createCmsEntryElasticsearchFullTextSearchPlugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["CmsEntryElasticsearchFullTextSearchPlugin","Plugin","models","params","constructor","apply","createCmsEntryElasticsearchFullTextSearchPlugin"],"sources":["CmsEntryElasticsearchFullTextSearchPlugin.ts"],"sourcesContent":["import { Plugin } from \"@webiny/plugins\";\nimport { ElasticsearchBoolQueryConfig } from \"@webiny/api-elasticsearch/types\";\nimport { CmsModel, CmsModelField } from \"@webiny/api-headless-cms/types\";\n\nexport interface CmsEntryElasticsearchFullTextSearchPluginCbParams {\n model: CmsModel;\n query: ElasticsearchBoolQueryConfig;\n term: string;\n fields: CmsModelField[];\n createFieldPath: (field: CmsModelField) => string;\n prepareTerm: (term: string) => string;\n}\nexport interface CmsEntryElasticsearchFullTextSearchPluginParams {\n models?: string[];\n apply: (params: CmsEntryElasticsearchFullTextSearchPluginCbParams) => void;\n}\nexport class CmsEntryElasticsearchFullTextSearchPlugin extends Plugin {\n public static override readonly type: string =\n \"headless-cms.elasticsearch.entry.fullTextSearch\";\n\n private readonly params: CmsEntryElasticsearchFullTextSearchPluginParams;\n\n public get models() {\n return this.params.models;\n }\n\n public constructor(params: CmsEntryElasticsearchFullTextSearchPluginParams) {\n super();\n this.params = params;\n }\n\n public apply(params: CmsEntryElasticsearchFullTextSearchPluginCbParams): void {\n return this.params.apply(params);\n }\n}\n\nexport const createCmsEntryElasticsearchFullTextSearchPlugin = (\n params: CmsEntryElasticsearchFullTextSearchPluginParams\n) => {\n return new CmsEntryElasticsearchFullTextSearchPlugin(params);\n};\n"],"mappings":";;;;;;;;;;;AAAA;;AAgBO,MAAMA,yCAAN,SAAwDC,eAAxD,CAA+D;EAMjD,IAANC,MAAM,GAAG;IAChB,OAAO,KAAKC,MAAL,CAAYD,MAAnB;EACH;;EAEME,WAAW,CAACD,MAAD,EAA0D;IACxE;IADwE;IAExE,KAAKA,MAAL,GAAcA,MAAd;EACH;;EAEME,KAAK,CAACF,MAAD,EAAkE;IAC1E,OAAO,KAAKA,MAAL,CAAYE,KAAZ,CAAkBF,MAAlB,CAAP;EACH;;AAjBiE;;;8BAAzDH,yC,UAEL,iD;;AAkBD,MAAMM,+CAA+C,GACxDH,MAD2D,IAE1D;EACD,OAAO,IAAIH,yCAAJ,CAA8CG,MAA9C,CAAP;AACH,CAJM"}
|
package/plugins/index.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export * from "./CmsEntryElasticsearchIndexPlugin";
|
|
|
4
4
|
export * from "./CmsEntryElasticsearchQueryBuilderValueSearchPlugin";
|
|
5
5
|
export * from "./CmsEntryElasticsearchQueryModifierPlugin";
|
|
6
6
|
export * from "./CmsEntryElasticsearchSortModifierPlugin";
|
|
7
|
+
export * from "./CmsEntryElasticsearchFullTextSearchPlugin";
|
package/plugins/index.js
CHANGED
|
@@ -80,4 +80,17 @@ Object.keys(_CmsEntryElasticsearchSortModifierPlugin).forEach(function (key) {
|
|
|
80
80
|
return _CmsEntryElasticsearchSortModifierPlugin[key];
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
var _CmsEntryElasticsearchFullTextSearchPlugin = require("./CmsEntryElasticsearchFullTextSearchPlugin");
|
|
86
|
+
|
|
87
|
+
Object.keys(_CmsEntryElasticsearchFullTextSearchPlugin).forEach(function (key) {
|
|
88
|
+
if (key === "default" || key === "__esModule") return;
|
|
89
|
+
if (key in exports && exports[key] === _CmsEntryElasticsearchFullTextSearchPlugin[key]) return;
|
|
90
|
+
Object.defineProperty(exports, key, {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return _CmsEntryElasticsearchFullTextSearchPlugin[key];
|
|
94
|
+
}
|
|
95
|
+
});
|
|
83
96
|
});
|
package/plugins/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./CmsEntryElasticsearchBodyModifierPlugin\";\nexport * from \"./CmsEntryElasticsearchFieldPlugin\";\nexport * from \"./CmsEntryElasticsearchIndexPlugin\";\nexport * from \"./CmsEntryElasticsearchQueryBuilderValueSearchPlugin\";\nexport * from \"./CmsEntryElasticsearchQueryModifierPlugin\";\nexport * from \"./CmsEntryElasticsearchSortModifierPlugin\";\n"],"mappings":";;;;;;AAAA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./CmsEntryElasticsearchBodyModifierPlugin\";\nexport * from \"./CmsEntryElasticsearchFieldPlugin\";\nexport * from \"./CmsEntryElasticsearchIndexPlugin\";\nexport * from \"./CmsEntryElasticsearchQueryBuilderValueSearchPlugin\";\nexport * from \"./CmsEntryElasticsearchQueryModifierPlugin\";\nexport * from \"./CmsEntryElasticsearchSortModifierPlugin\";\nexport * from \"./CmsEntryElasticsearchFullTextSearchPlugin\";\n"],"mappings":";;;;;;AAAA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
|