@deenruv/elasticsearch-plugin 1.0.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/LICENSE +23 -0
- package/README.md +122 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +20 -0
- package/lib/index.js.map +1 -0
- package/lib/src/api/api-extensions.d.ts +3 -0
- package/lib/src/api/api-extensions.js +148 -0
- package/lib/src/api/api-extensions.js.map +1 -0
- package/lib/src/api/custom-mappings.resolver.d.ts +12 -0
- package/lib/src/api/custom-mappings.resolver.js +47 -0
- package/lib/src/api/custom-mappings.resolver.js.map +1 -0
- package/lib/src/api/custom-script-fields.resolver.d.ts +12 -0
- package/lib/src/api/custom-script-fields.resolver.js +50 -0
- package/lib/src/api/custom-script-fields.resolver.js.map +1 -0
- package/lib/src/api/elasticsearch-resolver.d.ts +34 -0
- package/lib/src/api/elasticsearch-resolver.js +150 -0
- package/lib/src/api/elasticsearch-resolver.js.map +1 -0
- package/lib/src/build-elastic-body.d.ts +8 -0
- package/lib/src/build-elastic-body.js +173 -0
- package/lib/src/build-elastic-body.js.map +1 -0
- package/lib/src/constants.d.ts +3 -0
- package/lib/src/constants.js +7 -0
- package/lib/src/constants.js.map +1 -0
- package/lib/src/elasticsearch.health.d.ts +9 -0
- package/lib/src/elasticsearch.health.js +52 -0
- package/lib/src/elasticsearch.health.js.map +1 -0
- package/lib/src/elasticsearch.service.d.ts +56 -0
- package/lib/src/elasticsearch.service.js +469 -0
- package/lib/src/elasticsearch.service.js.map +1 -0
- package/lib/src/indexing/elasticsearch-index.service.d.ts +24 -0
- package/lib/src/indexing/elasticsearch-index.service.js +163 -0
- package/lib/src/indexing/elasticsearch-index.service.js.map +1 -0
- package/lib/src/indexing/indexer.controller.d.ts +98 -0
- package/lib/src/indexing/indexer.controller.js +790 -0
- package/lib/src/indexing/indexer.controller.js.map +1 -0
- package/lib/src/indexing/indexing-utils.d.ts +8 -0
- package/lib/src/indexing/indexing-utils.js +109 -0
- package/lib/src/indexing/indexing-utils.js.map +1 -0
- package/lib/src/options.d.ts +695 -0
- package/lib/src/options.js +59 -0
- package/lib/src/options.js.map +1 -0
- package/lib/src/plugin.d.ts +192 -0
- package/lib/src/plugin.js +371 -0
- package/lib/src/plugin.js.map +1 -0
- package/lib/src/types.d.ts +262 -0
- package/lib/src/types.js +17 -0
- package/lib/src/types.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
import { ClientOptions } from "@elastic/elasticsearch";
|
|
2
|
+
import { DeepRequired, EntityRelationPaths, ID, Injector, LanguageCode, Product, ProductVariant, RequestContext } from "@deenruv/core";
|
|
3
|
+
import { CustomMapping, CustomScriptMapping, ElasticSearchInput, ElasticSearchSortInput, GraphQlPrimitive, PrimitiveTypeVariations } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* Configuration options for the {@link ElasticsearchPlugin}.
|
|
7
|
+
*
|
|
8
|
+
* @docsCategory core plugins/ElasticsearchPlugin
|
|
9
|
+
* @docsPage ElasticsearchOptions
|
|
10
|
+
*/
|
|
11
|
+
export interface ElasticsearchOptions {
|
|
12
|
+
/**
|
|
13
|
+
* @description
|
|
14
|
+
* The host of the Elasticsearch server. May also be specified in `clientOptions.node`.
|
|
15
|
+
*
|
|
16
|
+
* @default 'http://localhost'
|
|
17
|
+
*/
|
|
18
|
+
host?: string;
|
|
19
|
+
/**
|
|
20
|
+
* @description
|
|
21
|
+
* The port of the Elasticsearch server. May also be specified in `clientOptions.node`.
|
|
22
|
+
*
|
|
23
|
+
* @default 9200
|
|
24
|
+
*/
|
|
25
|
+
port?: number;
|
|
26
|
+
/**
|
|
27
|
+
* @description
|
|
28
|
+
* Maximum amount of attempts made to connect to the ElasticSearch server on startup.
|
|
29
|
+
*
|
|
30
|
+
* @default 10
|
|
31
|
+
*/
|
|
32
|
+
connectionAttempts?: number;
|
|
33
|
+
/**
|
|
34
|
+
* @description
|
|
35
|
+
* Interval in milliseconds between attempts to connect to the ElasticSearch server on startup.
|
|
36
|
+
*
|
|
37
|
+
* @default 5000
|
|
38
|
+
*/
|
|
39
|
+
connectionAttemptInterval?: number;
|
|
40
|
+
/**
|
|
41
|
+
* @description
|
|
42
|
+
* Options to pass directly to the
|
|
43
|
+
* [Elasticsearch Node.js client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html). For example, to
|
|
44
|
+
* set authentication or other more advanced options.
|
|
45
|
+
* Note that if the `node` or `nodes` option is specified, it will override the values provided in the `host` and `port` options.
|
|
46
|
+
*/
|
|
47
|
+
clientOptions?: ClientOptions;
|
|
48
|
+
/**
|
|
49
|
+
* @description
|
|
50
|
+
* Prefix for the indices created by the plugin.
|
|
51
|
+
*
|
|
52
|
+
* @default
|
|
53
|
+
* 'deenruv-'
|
|
54
|
+
*/
|
|
55
|
+
indexPrefix?: string;
|
|
56
|
+
/**
|
|
57
|
+
* @description
|
|
58
|
+
* [These options](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/index-modules.html#index-modules-settings)
|
|
59
|
+
* are directly passed to index settings. To apply some settings indices will be recreated.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* // Configuring an English stemmer
|
|
64
|
+
* indexSettings: {
|
|
65
|
+
* analysis: {
|
|
66
|
+
* analyzer: {
|
|
67
|
+
* custom_analyzer: {
|
|
68
|
+
* tokenizer: 'standard',
|
|
69
|
+
* filter: [
|
|
70
|
+
* 'lowercase',
|
|
71
|
+
* 'english_stemmer'
|
|
72
|
+
* ]
|
|
73
|
+
* }
|
|
74
|
+
* },
|
|
75
|
+
* filter : {
|
|
76
|
+
* english_stemmer : {
|
|
77
|
+
* type : 'stemmer',
|
|
78
|
+
* name : 'english'
|
|
79
|
+
* }
|
|
80
|
+
* }
|
|
81
|
+
* }
|
|
82
|
+
* },
|
|
83
|
+
* ```
|
|
84
|
+
* A more complete example can be found in the discussion thread
|
|
85
|
+
* [How to make elastic plugin to search by substring with stemming](https://github.com/deenruv-ecommerce/deenruv/discussions/1066).
|
|
86
|
+
*
|
|
87
|
+
* @since 1.2.0
|
|
88
|
+
* @default
|
|
89
|
+
* {}
|
|
90
|
+
*/
|
|
91
|
+
indexSettings?: object;
|
|
92
|
+
/**
|
|
93
|
+
* @description
|
|
94
|
+
* This option allow to redefine or define new properties in mapping. More about elastic
|
|
95
|
+
* [mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html)
|
|
96
|
+
* After changing this option indices will be recreated.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* // Configuring custom analyzer for the `productName` field.
|
|
101
|
+
* indexMappingProperties: {
|
|
102
|
+
* productName: {
|
|
103
|
+
* type: 'text',
|
|
104
|
+
* analyzer:'custom_analyzer',
|
|
105
|
+
* fields: {
|
|
106
|
+
* keyword: {
|
|
107
|
+
* type: 'keyword',
|
|
108
|
+
* ignore_above: 256,
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* }
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* To reference a field defined by `customProductMappings` or `customProductVariantMappings`, you will
|
|
116
|
+
* need to prefix the name with `'product-<name>'` or `'variant-<name>'` respectively, e.g.:
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* customProductMappings: {
|
|
121
|
+
* variantCount: {
|
|
122
|
+
* graphQlType: 'Int!',
|
|
123
|
+
* valueFn: (product, variants) => variants.length,
|
|
124
|
+
* },
|
|
125
|
+
* },
|
|
126
|
+
* indexMappingProperties: {
|
|
127
|
+
* 'product-variantCount': {
|
|
128
|
+
* type: 'integer',
|
|
129
|
+
* }
|
|
130
|
+
* }
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* @since 1.2.0
|
|
134
|
+
* @default
|
|
135
|
+
* {}
|
|
136
|
+
*/
|
|
137
|
+
indexMappingProperties?: {
|
|
138
|
+
[indexName: string]: object;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* @description
|
|
142
|
+
* Products limit chunk size for each loop iteration when indexing products.
|
|
143
|
+
*
|
|
144
|
+
* @default 2500
|
|
145
|
+
* @since 2.1.7
|
|
146
|
+
*/
|
|
147
|
+
reindexProductsChunkSize?: number;
|
|
148
|
+
/**
|
|
149
|
+
* @description
|
|
150
|
+
* Index operations are performed in bulk, with each bulk operation containing a number of individual
|
|
151
|
+
* index operations. This option sets the maximum number of operations in the memory buffer before a
|
|
152
|
+
* bulk operation is executed.
|
|
153
|
+
*
|
|
154
|
+
* @default 3000
|
|
155
|
+
* @since 2.1.7
|
|
156
|
+
*/
|
|
157
|
+
reindexBulkOperationSizeLimit?: number;
|
|
158
|
+
/**
|
|
159
|
+
* @description
|
|
160
|
+
* Configuration of the internal Elasticsearch query.
|
|
161
|
+
*/
|
|
162
|
+
searchConfig?: SearchConfig;
|
|
163
|
+
/**
|
|
164
|
+
* @description
|
|
165
|
+
* Custom mappings may be defined which will add the defined data to the
|
|
166
|
+
* Elasticsearch index and expose that data via the SearchResult GraphQL type,
|
|
167
|
+
* adding a new `customMappings`, `customProductMappings` & `customProductVariantMappings` fields.
|
|
168
|
+
*
|
|
169
|
+
* The `graphQlType` property may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
|
|
170
|
+
* versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
|
|
171
|
+
*
|
|
172
|
+
* The `public` (default = `true`) property is used to reveal or hide the property in the GraphQL API schema.
|
|
173
|
+
* If this property is set to `false` it's not accessible in the `customMappings` field but it's still getting
|
|
174
|
+
* parsed to the elasticsearch index.
|
|
175
|
+
*
|
|
176
|
+
* This config option defines custom mappings which are accessible when the "groupByProduct"
|
|
177
|
+
* input options is set to `true`. In addition, custom variant mappings can be accessed by using
|
|
178
|
+
* the `customProductVariantMappings` field, which is always available.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* customProductMappings: {
|
|
183
|
+
* variantCount: {
|
|
184
|
+
* graphQlType: 'Int!',
|
|
185
|
+
* valueFn: (product, variants) => variants.length,
|
|
186
|
+
* },
|
|
187
|
+
* reviewRating: {
|
|
188
|
+
* graphQlType: 'Float',
|
|
189
|
+
* public: true,
|
|
190
|
+
* valueFn: product => (product.customFields as any).reviewRating,
|
|
191
|
+
* },
|
|
192
|
+
* priority: {
|
|
193
|
+
* graphQlType: 'Int!',
|
|
194
|
+
* public: false,
|
|
195
|
+
* valueFn: product => (product.customFields as any).priority,
|
|
196
|
+
* },
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```graphql
|
|
202
|
+
* query SearchProducts($input: SearchInput!) {
|
|
203
|
+
* search(input: $input) {
|
|
204
|
+
* totalItems
|
|
205
|
+
* items {
|
|
206
|
+
* productId
|
|
207
|
+
* productName
|
|
208
|
+
* customProductMappings {
|
|
209
|
+
* variantCount
|
|
210
|
+
* reviewRating
|
|
211
|
+
* }
|
|
212
|
+
* customMappings {
|
|
213
|
+
* ...on CustomProductMappings {
|
|
214
|
+
* variantCount
|
|
215
|
+
* reviewRating
|
|
216
|
+
* }
|
|
217
|
+
* }
|
|
218
|
+
* }
|
|
219
|
+
* }
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
customProductMappings?: {
|
|
224
|
+
[fieldName: string]: CustomMapping<[
|
|
225
|
+
Product,
|
|
226
|
+
ProductVariant[],
|
|
227
|
+
LanguageCode,
|
|
228
|
+
Injector,
|
|
229
|
+
RequestContext
|
|
230
|
+
]>;
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* @description
|
|
234
|
+
* This config option defines custom mappings which are accessible when the "groupByProduct"
|
|
235
|
+
* input options is set to `false`. In addition, custom product mappings can be accessed by using
|
|
236
|
+
* the `customProductMappings` field, which is always available.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```graphql
|
|
240
|
+
* query SearchProducts($input: SearchInput!) {
|
|
241
|
+
* search(input: $input) {
|
|
242
|
+
* totalItems
|
|
243
|
+
* items {
|
|
244
|
+
* productId
|
|
245
|
+
* productName
|
|
246
|
+
* customProductVariantMappings {
|
|
247
|
+
* weight
|
|
248
|
+
* }
|
|
249
|
+
* customMappings {
|
|
250
|
+
* ...on CustomProductVariantMappings {
|
|
251
|
+
* weight
|
|
252
|
+
* }
|
|
253
|
+
* }
|
|
254
|
+
* }
|
|
255
|
+
* }
|
|
256
|
+
* }
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
customProductVariantMappings?: {
|
|
260
|
+
[fieldName: string]: CustomMapping<[
|
|
261
|
+
ProductVariant,
|
|
262
|
+
LanguageCode,
|
|
263
|
+
Injector,
|
|
264
|
+
RequestContext
|
|
265
|
+
]>;
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* @description
|
|
269
|
+
* If set to `true`, updates to Products, ProductVariants and Collections will not immediately
|
|
270
|
+
* trigger an update to the search index. Instead, all these changes will be buffered and will
|
|
271
|
+
* only be run via a call to the `runPendingSearchIndexUpdates` mutation in the Admin API.
|
|
272
|
+
*
|
|
273
|
+
* This is very useful for installations with a large number of ProductVariants and/or
|
|
274
|
+
* Collections, as the buffering allows better control over when these expensive jobs are run,
|
|
275
|
+
* and also performs optimizations to minimize the amount of work that needs to be performed by
|
|
276
|
+
* the worker.
|
|
277
|
+
*
|
|
278
|
+
* @since 1.3.0
|
|
279
|
+
* @default false
|
|
280
|
+
*/
|
|
281
|
+
bufferUpdates?: boolean;
|
|
282
|
+
/**
|
|
283
|
+
* @description
|
|
284
|
+
* Additional product relations that will be fetched from DB while reindexing. This can be used
|
|
285
|
+
* in combination with `customProductMappings` to ensure that the required relations are joined
|
|
286
|
+
* before the `product` object is passed to the `valueFn`.
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* {
|
|
291
|
+
* hydrateProductRelations: ['assets.asset'],
|
|
292
|
+
* customProductMappings: {
|
|
293
|
+
* assetPreviews: {
|
|
294
|
+
* graphQlType: '[String!]',
|
|
295
|
+
* // Here we can be sure that the `product.assets` array is populated
|
|
296
|
+
* // with an Asset object
|
|
297
|
+
* valueFn: (product) => product.assets.map(a => a.asset.preview),
|
|
298
|
+
* }
|
|
299
|
+
* }
|
|
300
|
+
* }
|
|
301
|
+
* ```
|
|
302
|
+
*
|
|
303
|
+
* @default []
|
|
304
|
+
* @since 1.3.0
|
|
305
|
+
*/
|
|
306
|
+
hydrateProductRelations?: Array<EntityRelationPaths<Product>>;
|
|
307
|
+
/**
|
|
308
|
+
* @description
|
|
309
|
+
* Additional variant relations that will be fetched from DB while reindexing. See
|
|
310
|
+
* `hydrateProductRelations` for more explanation and a usage example.
|
|
311
|
+
*
|
|
312
|
+
* @default []
|
|
313
|
+
* @since 1.3.0
|
|
314
|
+
*/
|
|
315
|
+
hydrateProductVariantRelations?: Array<EntityRelationPaths<ProductVariant>>;
|
|
316
|
+
/**
|
|
317
|
+
* @description
|
|
318
|
+
* Allows the `SearchInput` type to be extended with new input fields. This allows arbitrary
|
|
319
|
+
* data to be passed in, which can then be used e.g. in the `mapQuery()` function or
|
|
320
|
+
* custom `scriptFields` functions.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* extendSearchInputType: {
|
|
325
|
+
* longitude: 'Float',
|
|
326
|
+
* latitude: 'Float',
|
|
327
|
+
* radius: 'Float',
|
|
328
|
+
* }
|
|
329
|
+
* ```
|
|
330
|
+
*
|
|
331
|
+
* This allows the search query to include these new fields:
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```graphql
|
|
335
|
+
* query {
|
|
336
|
+
* search(input: {
|
|
337
|
+
* longitude: 101.7117,
|
|
338
|
+
* latitude: 3.1584,
|
|
339
|
+
* radius: 50.00
|
|
340
|
+
* }) {
|
|
341
|
+
* items {
|
|
342
|
+
* productName
|
|
343
|
+
* }
|
|
344
|
+
* }
|
|
345
|
+
* }
|
|
346
|
+
* ```
|
|
347
|
+
*
|
|
348
|
+
* @default {}
|
|
349
|
+
* @since 1.3.0
|
|
350
|
+
*/
|
|
351
|
+
extendSearchInputType?: {
|
|
352
|
+
[name: string]: PrimitiveTypeVariations<GraphQlPrimitive>;
|
|
353
|
+
};
|
|
354
|
+
/**
|
|
355
|
+
* @description
|
|
356
|
+
* Adds a list of sort parameters. This is mostly important to make the
|
|
357
|
+
* correct sort order values available inside `input` parameter of the `mapSort` option.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```ts
|
|
361
|
+
* extendSearchSortType: ["distance"]
|
|
362
|
+
* ```
|
|
363
|
+
*
|
|
364
|
+
* will extend the `SearchResultSortParameter` input type like this:
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```GraphQl
|
|
368
|
+
* extend input SearchResultSortParameter {
|
|
369
|
+
* distance: SortOrder
|
|
370
|
+
* }
|
|
371
|
+
* ```
|
|
372
|
+
*
|
|
373
|
+
* @default []
|
|
374
|
+
* @since 1.4.0
|
|
375
|
+
*/
|
|
376
|
+
extendSearchSortType?: string[];
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* @description
|
|
380
|
+
* Configuration options for the internal Elasticsearch query which is generated when performing a search.
|
|
381
|
+
*
|
|
382
|
+
* @docsCategory core plugins/ElasticsearchPlugin
|
|
383
|
+
* @docsPage ElasticsearchOptions
|
|
384
|
+
*/
|
|
385
|
+
export interface SearchConfig {
|
|
386
|
+
/**
|
|
387
|
+
* @description
|
|
388
|
+
* The maximum number of FacetValues to return from the search query. Internally, this
|
|
389
|
+
* value sets the "size" property of an Elasticsearch aggregation.
|
|
390
|
+
*
|
|
391
|
+
* @default
|
|
392
|
+
* 50
|
|
393
|
+
*/
|
|
394
|
+
facetValueMaxSize?: number;
|
|
395
|
+
/**
|
|
396
|
+
* @description
|
|
397
|
+
* The maximum number of Collections to return from the search query. Internally, this
|
|
398
|
+
* value sets the "size" property of an Elasticsearch aggregation.
|
|
399
|
+
*
|
|
400
|
+
* @since 1.1.0
|
|
401
|
+
* @default
|
|
402
|
+
* 50
|
|
403
|
+
*/
|
|
404
|
+
collectionMaxSize?: number;
|
|
405
|
+
/**
|
|
406
|
+
* @description
|
|
407
|
+
* The maximum number of totalItems to return from the search query. Internally, this
|
|
408
|
+
* value sets the "track_total_hits" property of an Elasticsearch query.
|
|
409
|
+
* If this parameter is set to "True", accurate count of totalItems will be returned.
|
|
410
|
+
* If this parameter is set to "False", totalItems will be returned as 0.
|
|
411
|
+
* If this parameter is set to integer, accurate count of totalItems will be returned not bigger than integer.
|
|
412
|
+
*
|
|
413
|
+
* @since 1.2.0
|
|
414
|
+
* @default
|
|
415
|
+
* 10000
|
|
416
|
+
*/
|
|
417
|
+
totalItemsMaxSize?: number | boolean;
|
|
418
|
+
/**
|
|
419
|
+
* @description
|
|
420
|
+
* Defines the
|
|
421
|
+
* [multi match type](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#multi-match-types)
|
|
422
|
+
* used when matching against a search term.
|
|
423
|
+
*
|
|
424
|
+
* @default
|
|
425
|
+
* 'best_fields'
|
|
426
|
+
*/
|
|
427
|
+
multiMatchType?: 'best_fields' | 'most_fields' | 'cross_fields' | 'phrase' | 'phrase_prefix' | 'bool_prefix';
|
|
428
|
+
/**
|
|
429
|
+
* @description
|
|
430
|
+
* Set custom boost values for particular fields when matching against a search term.
|
|
431
|
+
*/
|
|
432
|
+
boostFields?: BoostFieldsConfig;
|
|
433
|
+
/**
|
|
434
|
+
* @description
|
|
435
|
+
* The interval used to group search results into buckets according to price range. For example, setting this to
|
|
436
|
+
* `2000` will group into buckets every $20.00:
|
|
437
|
+
*
|
|
438
|
+
* ```json
|
|
439
|
+
* {
|
|
440
|
+
* "data": {
|
|
441
|
+
* "search": {
|
|
442
|
+
* "totalItems": 32,
|
|
443
|
+
* "priceRange": {
|
|
444
|
+
* "buckets": [
|
|
445
|
+
* {
|
|
446
|
+
* "to": 2000,
|
|
447
|
+
* "count": 21
|
|
448
|
+
* },
|
|
449
|
+
* {
|
|
450
|
+
* "to": 4000,
|
|
451
|
+
* "count": 7
|
|
452
|
+
* },
|
|
453
|
+
* {
|
|
454
|
+
* "to": 6000,
|
|
455
|
+
* "count": 3
|
|
456
|
+
* },
|
|
457
|
+
* {
|
|
458
|
+
* "to": 12000,
|
|
459
|
+
* "count": 1
|
|
460
|
+
* }
|
|
461
|
+
* ]
|
|
462
|
+
* }
|
|
463
|
+
* }
|
|
464
|
+
* }
|
|
465
|
+
* }
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
priceRangeBucketInterval?: number;
|
|
469
|
+
/**
|
|
470
|
+
* @description
|
|
471
|
+
* This config option allows the the modification of the whole (already built) search query. This allows
|
|
472
|
+
* for e.g. wildcard / fuzzy searches on the index.
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* mapQuery: (query, input, searchConfig, channelId, enabledOnly){
|
|
477
|
+
* if(query.bool.must){
|
|
478
|
+
* delete query.bool.must;
|
|
479
|
+
* }
|
|
480
|
+
* query.bool.should = [
|
|
481
|
+
* {
|
|
482
|
+
* query_string: {
|
|
483
|
+
* query: "*" + term + "*",
|
|
484
|
+
* fields: [
|
|
485
|
+
* `productName^${searchConfig.boostFields.productName}`,
|
|
486
|
+
* `productVariantName^${searchConfig.boostFields.productVariantName}`,
|
|
487
|
+
* ]
|
|
488
|
+
* }
|
|
489
|
+
* },
|
|
490
|
+
* {
|
|
491
|
+
* multi_match: {
|
|
492
|
+
* query: term,
|
|
493
|
+
* type: searchConfig.multiMatchType,
|
|
494
|
+
* fields: [
|
|
495
|
+
* `description^${searchConfig.boostFields.description}`,
|
|
496
|
+
* `sku^${searchConfig.boostFields.sku}`,
|
|
497
|
+
* ],
|
|
498
|
+
* },
|
|
499
|
+
* },
|
|
500
|
+
* ];
|
|
501
|
+
*
|
|
502
|
+
* return query;
|
|
503
|
+
* }
|
|
504
|
+
* ```
|
|
505
|
+
*/
|
|
506
|
+
mapQuery?: (query: any, input: ElasticSearchInput, searchConfig: DeepRequired<SearchConfig>, channelId: ID, enabledOnly: boolean) => any;
|
|
507
|
+
/**
|
|
508
|
+
* @description
|
|
509
|
+
* Sets `script_fields` inside the elasticsearch body which allows returning a script evaluation for each hit.
|
|
510
|
+
*
|
|
511
|
+
* The script field definition consists of three properties:
|
|
512
|
+
*
|
|
513
|
+
* * `graphQlType`: This is the type that will be returned when this script field is queried
|
|
514
|
+
* via the GraphQL API. It may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
|
|
515
|
+
* versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
|
|
516
|
+
* * `context`: determines whether this script field is available when grouping by product. Can be
|
|
517
|
+
* `product`, `variant` or `both`.
|
|
518
|
+
* * `scriptFn`: This is the function to run on each hit. Should return an object with a `script` property,
|
|
519
|
+
* as covered in the
|
|
520
|
+
* [Elasticsearch script fields docs](https://www.elastic.co/guide/en/elasticsearch/reference/7.15/search-fields.html#script-fields)
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```ts
|
|
524
|
+
* extendSearchInputType: {
|
|
525
|
+
* latitude: 'Float',
|
|
526
|
+
* longitude: 'Float',
|
|
527
|
+
* },
|
|
528
|
+
* indexMappingProperties: {
|
|
529
|
+
* // The `product-location` field corresponds to the `location` customProductMapping
|
|
530
|
+
* // defined below. Here we specify that it would be index as a `geo_point` type,
|
|
531
|
+
* // which will allow us to perform geo-spacial calculations on it in our script field.
|
|
532
|
+
* 'product-location': {
|
|
533
|
+
* type: 'geo_point', // contains function arcDistance
|
|
534
|
+
* },
|
|
535
|
+
* },
|
|
536
|
+
* customProductMappings: {
|
|
537
|
+
* location: {
|
|
538
|
+
* graphQlType: 'String',
|
|
539
|
+
* valueFn: (product: Product) => {
|
|
540
|
+
* // Assume that the Product entity has this customField defined
|
|
541
|
+
* const custom = product.customFields.location;
|
|
542
|
+
* return `${custom.latitude},${custom.longitude}`;
|
|
543
|
+
* },
|
|
544
|
+
* }
|
|
545
|
+
* },
|
|
546
|
+
* searchConfig: {
|
|
547
|
+
* scriptFields: {
|
|
548
|
+
* distance: {
|
|
549
|
+
* graphQlType: 'Float!',
|
|
550
|
+
* // Run this script only when grouping results by product
|
|
551
|
+
* context: 'product',
|
|
552
|
+
* scriptFn: (input) => {
|
|
553
|
+
* // The SearchInput was extended with latitude and longitude
|
|
554
|
+
* // via the `extendSearchInputType` option above.
|
|
555
|
+
* const lat = input.latitude;
|
|
556
|
+
* const lon = input.longitude;
|
|
557
|
+
* return {
|
|
558
|
+
* script: `doc['product-location'].arcDistance(${lat}, ${lon})`,
|
|
559
|
+
* }
|
|
560
|
+
* }
|
|
561
|
+
* }
|
|
562
|
+
* }
|
|
563
|
+
* }
|
|
564
|
+
* ```
|
|
565
|
+
*
|
|
566
|
+
* @since 1.3.0
|
|
567
|
+
*/
|
|
568
|
+
scriptFields?: {
|
|
569
|
+
[fieldName: string]: CustomScriptMapping<[ElasticSearchInput]>;
|
|
570
|
+
};
|
|
571
|
+
/**
|
|
572
|
+
* @description
|
|
573
|
+
* Allows extending the `sort` input of the elasticsearch body as covered in
|
|
574
|
+
* [Elasticsearch sort docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html)
|
|
575
|
+
*
|
|
576
|
+
* The `sort` input parameter contains the ElasticSearchSortInput generated for the default sort parameters "name" and "price".
|
|
577
|
+
* If neither of those are applied it will be empty.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* mapSort: (sort, input) => {
|
|
582
|
+
* // Assuming `extendSearchSortType: ["priority"]`
|
|
583
|
+
* // Assuming priority is never undefined
|
|
584
|
+
* const { priority } = input.sort;
|
|
585
|
+
* return [
|
|
586
|
+
* ...sort,
|
|
587
|
+
* {
|
|
588
|
+
* // The `product-priority` field corresponds to the `priority` customProductMapping
|
|
589
|
+
* // Depending on the index type, this field might require a
|
|
590
|
+
* // more detailed input (example: 'productName.keyword')
|
|
591
|
+
* ["product-priority"]: {
|
|
592
|
+
* order: priority === SortOrder.ASC ? 'asc' : 'desc'
|
|
593
|
+
* }
|
|
594
|
+
* }
|
|
595
|
+
* ];
|
|
596
|
+
* }
|
|
597
|
+
* ```
|
|
598
|
+
*
|
|
599
|
+
* A more generic example would be a sort function based on a product location like this:
|
|
600
|
+
* @example
|
|
601
|
+
* ```ts
|
|
602
|
+
* extendSearchInputType: {
|
|
603
|
+
* latitude: 'Float',
|
|
604
|
+
* longitude: 'Float',
|
|
605
|
+
* },
|
|
606
|
+
* extendSearchSortType: ["distance"],
|
|
607
|
+
* indexMappingProperties: {
|
|
608
|
+
* // The `product-location` field corresponds to the `location` customProductMapping
|
|
609
|
+
* // defined below. Here we specify that it would be index as a `geo_point` type,
|
|
610
|
+
* // which will allow us to perform geo-spacial calculations on it in our script field.
|
|
611
|
+
* 'product-location': {
|
|
612
|
+
* type: 'geo_point',
|
|
613
|
+
* },
|
|
614
|
+
* },
|
|
615
|
+
* customProductMappings: {
|
|
616
|
+
* location: {
|
|
617
|
+
* graphQlType: 'String',
|
|
618
|
+
* valueFn: (product: Product) => {
|
|
619
|
+
* // Assume that the Product entity has this customField defined
|
|
620
|
+
* const custom = product.customFields.location;
|
|
621
|
+
* return `${custom.latitude},${custom.longitude}`;
|
|
622
|
+
* },
|
|
623
|
+
* }
|
|
624
|
+
* },
|
|
625
|
+
* searchConfig: {
|
|
626
|
+
* mapSort: (sort, input) => {
|
|
627
|
+
* // Assuming distance is never undefined
|
|
628
|
+
* const { distance } = input.sort;
|
|
629
|
+
* return [
|
|
630
|
+
* ...sort,
|
|
631
|
+
* {
|
|
632
|
+
* ["_geo_distance"]: {
|
|
633
|
+
* "product-location": [
|
|
634
|
+
* input.longitude,
|
|
635
|
+
* input.latitude
|
|
636
|
+
* ],
|
|
637
|
+
* order: distance === SortOrder.ASC ? 'asc' : 'desc',
|
|
638
|
+
* unit: "km"
|
|
639
|
+
* }
|
|
640
|
+
* }
|
|
641
|
+
* ];
|
|
642
|
+
* }
|
|
643
|
+
* }
|
|
644
|
+
* ```
|
|
645
|
+
*
|
|
646
|
+
* @default {}
|
|
647
|
+
* @since 1.4.0
|
|
648
|
+
*/
|
|
649
|
+
mapSort?: (sort: ElasticSearchSortInput, input: ElasticSearchInput) => ElasticSearchSortInput;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* @description
|
|
653
|
+
* Configuration for [boosting](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#field-boost)
|
|
654
|
+
* the scores of given fields when performing a search against a term.
|
|
655
|
+
*
|
|
656
|
+
* Boosting a field acts as a score multiplier for matches against that field.
|
|
657
|
+
*
|
|
658
|
+
* @docsCategory core plugins/ElasticsearchPlugin
|
|
659
|
+
* @docsPage ElasticsearchOptions
|
|
660
|
+
*/
|
|
661
|
+
export interface BoostFieldsConfig {
|
|
662
|
+
/**
|
|
663
|
+
* @description
|
|
664
|
+
* Defines the boost factor for the productName field.
|
|
665
|
+
*
|
|
666
|
+
* @default 1
|
|
667
|
+
*/
|
|
668
|
+
productName?: number;
|
|
669
|
+
/**
|
|
670
|
+
* @description
|
|
671
|
+
* Defines the boost factor for the productVariantName field.
|
|
672
|
+
*
|
|
673
|
+
* @default 1
|
|
674
|
+
*/
|
|
675
|
+
productVariantName?: number;
|
|
676
|
+
/**
|
|
677
|
+
* @description
|
|
678
|
+
* Defines the boost factor for the description field.
|
|
679
|
+
*
|
|
680
|
+
* @default 1
|
|
681
|
+
*/
|
|
682
|
+
description?: number;
|
|
683
|
+
/**
|
|
684
|
+
* @description
|
|
685
|
+
* Defines the boost factor for the sku field.
|
|
686
|
+
*
|
|
687
|
+
* @default 1
|
|
688
|
+
*/
|
|
689
|
+
sku?: number;
|
|
690
|
+
}
|
|
691
|
+
export type ElasticsearchRuntimeOptions = DeepRequired<Omit<ElasticsearchOptions, "clientOptions">> & {
|
|
692
|
+
clientOptions?: ClientOptions;
|
|
693
|
+
};
|
|
694
|
+
export declare const defaultOptions: ElasticsearchRuntimeOptions;
|
|
695
|
+
export declare function mergeWithDefaults(userOptions: ElasticsearchOptions): ElasticsearchRuntimeOptions;
|