@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.
Files changed (48) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +122 -0
  3. package/lib/index.d.ts +3 -0
  4. package/lib/index.js +20 -0
  5. package/lib/index.js.map +1 -0
  6. package/lib/src/api/api-extensions.d.ts +3 -0
  7. package/lib/src/api/api-extensions.js +148 -0
  8. package/lib/src/api/api-extensions.js.map +1 -0
  9. package/lib/src/api/custom-mappings.resolver.d.ts +12 -0
  10. package/lib/src/api/custom-mappings.resolver.js +47 -0
  11. package/lib/src/api/custom-mappings.resolver.js.map +1 -0
  12. package/lib/src/api/custom-script-fields.resolver.d.ts +12 -0
  13. package/lib/src/api/custom-script-fields.resolver.js +50 -0
  14. package/lib/src/api/custom-script-fields.resolver.js.map +1 -0
  15. package/lib/src/api/elasticsearch-resolver.d.ts +34 -0
  16. package/lib/src/api/elasticsearch-resolver.js +150 -0
  17. package/lib/src/api/elasticsearch-resolver.js.map +1 -0
  18. package/lib/src/build-elastic-body.d.ts +8 -0
  19. package/lib/src/build-elastic-body.js +173 -0
  20. package/lib/src/build-elastic-body.js.map +1 -0
  21. package/lib/src/constants.d.ts +3 -0
  22. package/lib/src/constants.js +7 -0
  23. package/lib/src/constants.js.map +1 -0
  24. package/lib/src/elasticsearch.health.d.ts +9 -0
  25. package/lib/src/elasticsearch.health.js +52 -0
  26. package/lib/src/elasticsearch.health.js.map +1 -0
  27. package/lib/src/elasticsearch.service.d.ts +56 -0
  28. package/lib/src/elasticsearch.service.js +469 -0
  29. package/lib/src/elasticsearch.service.js.map +1 -0
  30. package/lib/src/indexing/elasticsearch-index.service.d.ts +24 -0
  31. package/lib/src/indexing/elasticsearch-index.service.js +163 -0
  32. package/lib/src/indexing/elasticsearch-index.service.js.map +1 -0
  33. package/lib/src/indexing/indexer.controller.d.ts +98 -0
  34. package/lib/src/indexing/indexer.controller.js +790 -0
  35. package/lib/src/indexing/indexer.controller.js.map +1 -0
  36. package/lib/src/indexing/indexing-utils.d.ts +8 -0
  37. package/lib/src/indexing/indexing-utils.js +109 -0
  38. package/lib/src/indexing/indexing-utils.js.map +1 -0
  39. package/lib/src/options.d.ts +695 -0
  40. package/lib/src/options.js +59 -0
  41. package/lib/src/options.js.map +1 -0
  42. package/lib/src/plugin.d.ts +192 -0
  43. package/lib/src/plugin.js +371 -0
  44. package/lib/src/plugin.js.map +1 -0
  45. package/lib/src/types.d.ts +262 -0
  46. package/lib/src/types.js +17 -0
  47. package/lib/src/types.js.map +1 -0
  48. 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;