elasticlink 0.3.0-beta → 0.4.0-beta

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 (109) hide show
  1. package/README.md +61 -14
  2. package/dist/__tests__/aggregation-builder.test.d.ts +2 -0
  3. package/dist/__tests__/aggregation-builder.test.d.ts.map +1 -0
  4. package/dist/__tests__/aggregation-builder.test.js +622 -0
  5. package/dist/__tests__/bulk.test.d.ts +2 -0
  6. package/dist/__tests__/bulk.test.d.ts.map +1 -0
  7. package/dist/__tests__/bulk.test.js +679 -0
  8. package/dist/__tests__/examples.test.d.ts +2 -0
  9. package/dist/__tests__/examples.test.d.ts.map +1 -0
  10. package/dist/__tests__/examples.test.js +2123 -0
  11. package/dist/__tests__/fixtures/finance.d.ts +58 -0
  12. package/dist/__tests__/fixtures/finance.d.ts.map +1 -0
  13. package/dist/__tests__/fixtures/finance.js +73 -0
  14. package/dist/__tests__/fixtures/legal.d.ts +14 -0
  15. package/dist/__tests__/fixtures/legal.d.ts.map +1 -0
  16. package/dist/__tests__/fixtures/legal.js +27 -0
  17. package/dist/__tests__/fixtures/real-estate.d.ts +31 -0
  18. package/dist/__tests__/fixtures/real-estate.d.ts.map +1 -0
  19. package/dist/__tests__/fixtures/real-estate.js +39 -0
  20. package/dist/__tests__/index-management.test.d.ts +2 -0
  21. package/dist/__tests__/index-management.test.d.ts.map +1 -0
  22. package/dist/__tests__/index-management.test.js +1699 -0
  23. package/dist/__tests__/integration/aggregation.integration.test.d.ts +2 -0
  24. package/dist/__tests__/integration/aggregation.integration.test.d.ts.map +1 -0
  25. package/dist/__tests__/integration/aggregation.integration.test.js +188 -0
  26. package/dist/__tests__/integration/bulk.integration.test.d.ts +2 -0
  27. package/dist/__tests__/integration/bulk.integration.test.d.ts.map +1 -0
  28. package/dist/__tests__/integration/bulk.integration.test.js +90 -0
  29. package/dist/__tests__/integration/fixtures/finance.d.ts +37 -0
  30. package/dist/__tests__/integration/fixtures/finance.d.ts.map +1 -0
  31. package/dist/__tests__/integration/fixtures/finance.js +58 -0
  32. package/dist/__tests__/integration/fixtures/legal.d.ts +38 -0
  33. package/dist/__tests__/integration/fixtures/legal.d.ts.map +1 -0
  34. package/dist/__tests__/integration/fixtures/legal.js +65 -0
  35. package/dist/__tests__/integration/fixtures/real-estate.d.ts +17 -0
  36. package/dist/__tests__/integration/fixtures/real-estate.d.ts.map +1 -0
  37. package/dist/__tests__/integration/fixtures/real-estate.js +28 -0
  38. package/dist/__tests__/integration/helpers.d.ts +15 -0
  39. package/dist/__tests__/integration/helpers.d.ts.map +1 -0
  40. package/dist/__tests__/integration/helpers.js +21 -0
  41. package/dist/__tests__/integration/index-management.integration.test.d.ts +2 -0
  42. package/dist/__tests__/integration/index-management.integration.test.d.ts.map +1 -0
  43. package/dist/__tests__/integration/index-management.integration.test.js +67 -0
  44. package/dist/__tests__/integration/multi-search.integration.test.d.ts +2 -0
  45. package/dist/__tests__/integration/multi-search.integration.test.d.ts.map +1 -0
  46. package/dist/__tests__/integration/multi-search.integration.test.js +49 -0
  47. package/dist/__tests__/integration/query.integration.test.d.ts +2 -0
  48. package/dist/__tests__/integration/query.integration.test.d.ts.map +1 -0
  49. package/dist/__tests__/integration/query.integration.test.js +101 -0
  50. package/dist/__tests__/integration/suggester.integration.test.d.ts +2 -0
  51. package/dist/__tests__/integration/suggester.integration.test.d.ts.map +1 -0
  52. package/dist/__tests__/integration/suggester.integration.test.js +42 -0
  53. package/dist/__tests__/multi-search.test.d.ts +2 -0
  54. package/dist/__tests__/multi-search.test.d.ts.map +1 -0
  55. package/dist/__tests__/multi-search.test.js +325 -0
  56. package/dist/__tests__/query-builder-extensions.test.d.ts +2 -0
  57. package/dist/__tests__/query-builder-extensions.test.d.ts.map +1 -0
  58. package/dist/__tests__/query-builder-extensions.test.js +436 -0
  59. package/dist/__tests__/query-builder.test.d.ts +2 -0
  60. package/dist/__tests__/query-builder.test.d.ts.map +1 -0
  61. package/dist/__tests__/query-builder.test.js +5482 -0
  62. package/dist/__tests__/settings-presets.test.d.ts +2 -0
  63. package/dist/__tests__/settings-presets.test.d.ts.map +1 -0
  64. package/dist/__tests__/settings-presets.test.js +183 -0
  65. package/dist/__tests__/suggester.test.d.ts +2 -0
  66. package/dist/__tests__/suggester.test.d.ts.map +1 -0
  67. package/dist/__tests__/suggester.test.js +1006 -0
  68. package/dist/aggregation.builder.d.ts.map +1 -1
  69. package/dist/aggregation.builder.js +101 -94
  70. package/dist/aggregation.types.d.ts +10 -9
  71. package/dist/aggregation.types.d.ts.map +1 -1
  72. package/dist/bulk.builder.d.ts +11 -1
  73. package/dist/bulk.builder.d.ts.map +1 -1
  74. package/dist/bulk.builder.js +10 -11
  75. package/dist/bulk.types.d.ts.map +1 -1
  76. package/dist/field.helpers.d.ts +59 -4
  77. package/dist/field.helpers.d.ts.map +1 -1
  78. package/dist/field.helpers.js +87 -4
  79. package/dist/field.types.d.ts +78 -1
  80. package/dist/field.types.d.ts.map +1 -1
  81. package/dist/index-management.builder.d.ts +15 -3
  82. package/dist/index-management.builder.d.ts.map +1 -1
  83. package/dist/index-management.builder.js +32 -8
  84. package/dist/index-management.types.d.ts +27 -3
  85. package/dist/index-management.types.d.ts.map +1 -1
  86. package/dist/index.d.ts +3 -2
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +3 -1
  89. package/dist/mapping.builder.d.ts +16 -3
  90. package/dist/mapping.builder.d.ts.map +1 -1
  91. package/dist/mapping.builder.js +22 -7
  92. package/dist/mapping.types.d.ts +29 -6
  93. package/dist/mapping.types.d.ts.map +1 -1
  94. package/dist/multi-search.builder.d.ts +1 -1
  95. package/dist/multi-search.builder.d.ts.map +1 -1
  96. package/dist/multi-search.builder.js +5 -3
  97. package/dist/query.builder.d.ts +0 -4
  98. package/dist/query.builder.d.ts.map +1 -1
  99. package/dist/query.builder.js +104 -183
  100. package/dist/query.types.d.ts +59 -5
  101. package/dist/query.types.d.ts.map +1 -1
  102. package/dist/settings.presets.d.ts +98 -0
  103. package/dist/settings.presets.d.ts.map +1 -0
  104. package/dist/settings.presets.js +115 -0
  105. package/dist/suggester.builder.d.ts.map +1 -1
  106. package/dist/suggester.builder.js +1 -0
  107. package/dist/suggester.types.d.ts.map +1 -1
  108. package/dist/vector.types.d.ts.map +1 -1
  109. package/package.json +6 -3
@@ -0,0 +1,1699 @@
1
+ import { indexBuilder, mappings, text, keyword, float, long, integer, short, byte, double, date, boolean, denseVector, nested, scaledFloat, geoPoint, dateRange, percolator, completion, halfFloat, geoShape, ip, binary, integerRange, floatRange, longRange, doubleRange, object, alias, matchOnlyText, searchAsYouType, constantKeyword, wildcardField, flattened, quantizedDenseVector } from '..';
2
+ describe('Index Management', () => {
3
+ describe('Builder behavior', () => {
4
+ it('should return empty object for empty builder', () => {
5
+ const result = indexBuilder().build();
6
+ expect(result).toMatchInlineSnapshot(`{}`);
7
+ });
8
+ it('should replace mappings when called twice', () => {
9
+ const result = indexBuilder().mappings({ name: text() }).mappings({ market_cap: float() }).build();
10
+ expect(result).toMatchInlineSnapshot(`
11
+ {
12
+ "mappings": {
13
+ "dynamic": "strict",
14
+ "properties": {
15
+ "market_cap": {
16
+ "type": "float",
17
+ },
18
+ },
19
+ },
20
+ }
21
+ `);
22
+ });
23
+ it('should replace settings when called twice', () => {
24
+ const result = indexBuilder().settings({ number_of_shards: 3 }).settings({ number_of_replicas: 2 }).build();
25
+ expect(result).toMatchInlineSnapshot(`
26
+ {
27
+ "settings": {
28
+ "number_of_replicas": 2,
29
+ },
30
+ }
31
+ `);
32
+ });
33
+ });
34
+ describe('Mappings', () => {
35
+ it('should build basic mappings', () => {
36
+ const result = indexBuilder()
37
+ .mappings({
38
+ name: text(),
39
+ market_cap: float(),
40
+ asset_class: keyword()
41
+ })
42
+ .build();
43
+ expect(result).toMatchInlineSnapshot(`
44
+ {
45
+ "mappings": {
46
+ "dynamic": "strict",
47
+ "properties": {
48
+ "asset_class": {
49
+ "type": "keyword",
50
+ },
51
+ "market_cap": {
52
+ "type": "float",
53
+ },
54
+ "name": {
55
+ "type": "text",
56
+ },
57
+ },
58
+ },
59
+ }
60
+ `);
61
+ });
62
+ it('should build mappings with analyzers', () => {
63
+ const result = indexBuilder()
64
+ .mappings({
65
+ name: text({
66
+ analyzer: 'standard',
67
+ search_analyzer: 'english'
68
+ })
69
+ })
70
+ .build();
71
+ expect(result).toMatchInlineSnapshot(`
72
+ {
73
+ "mappings": {
74
+ "dynamic": "strict",
75
+ "properties": {
76
+ "name": {
77
+ "analyzer": "standard",
78
+ "search_analyzer": "english",
79
+ "type": "text",
80
+ },
81
+ },
82
+ },
83
+ }
84
+ `);
85
+ });
86
+ it('should build mappings with multi-fields', () => {
87
+ const result = indexBuilder()
88
+ .mappings({
89
+ name: text({
90
+ fields: {
91
+ keyword: { type: 'keyword' },
92
+ ngram: { type: 'text', analyzer: 'ngram' }
93
+ }
94
+ })
95
+ })
96
+ .build();
97
+ expect(result).toMatchInlineSnapshot(`
98
+ {
99
+ "mappings": {
100
+ "dynamic": "strict",
101
+ "properties": {
102
+ "name": {
103
+ "fields": {
104
+ "keyword": {
105
+ "type": "keyword",
106
+ },
107
+ "ngram": {
108
+ "analyzer": "ngram",
109
+ "type": "text",
110
+ },
111
+ },
112
+ "type": "text",
113
+ },
114
+ },
115
+ },
116
+ }
117
+ `);
118
+ });
119
+ it('should build mappings with nested fields', () => {
120
+ const result = indexBuilder()
121
+ .mappings({
122
+ tranches: nested({
123
+ maturity: keyword(),
124
+ currency: keyword()
125
+ })
126
+ })
127
+ .build();
128
+ expect(result).toMatchInlineSnapshot(`
129
+ {
130
+ "mappings": {
131
+ "dynamic": "strict",
132
+ "properties": {
133
+ "tranches": {
134
+ "properties": {
135
+ "currency": {
136
+ "type": "keyword",
137
+ },
138
+ "maturity": {
139
+ "type": "keyword",
140
+ },
141
+ },
142
+ "type": "nested",
143
+ },
144
+ },
145
+ },
146
+ }
147
+ `);
148
+ });
149
+ it('should build mappings with dense_vector', () => {
150
+ const result = indexBuilder()
151
+ .mappings({
152
+ embedding: denseVector({
153
+ dims: 384,
154
+ index_options: {
155
+ type: 'hnsw',
156
+ m: 16,
157
+ ef_construction: 100
158
+ }
159
+ })
160
+ })
161
+ .build();
162
+ expect(result).toMatchInlineSnapshot(`
163
+ {
164
+ "mappings": {
165
+ "dynamic": "strict",
166
+ "properties": {
167
+ "embedding": {
168
+ "dims": 384,
169
+ "index_options": {
170
+ "ef_construction": 100,
171
+ "m": 16,
172
+ "type": "hnsw",
173
+ },
174
+ "type": "dense_vector",
175
+ },
176
+ },
177
+ },
178
+ }
179
+ `);
180
+ });
181
+ });
182
+ describe('Field type coverage', () => {
183
+ it('should support integer field type', () => {
184
+ const result = indexBuilder().mappings({ count: integer() }).build();
185
+ expect(result.mappings?.properties.count?.type).toBe('integer');
186
+ });
187
+ it('should support boolean field type', () => {
188
+ const result = indexBuilder().mappings({ active: boolean() }).build();
189
+ expect(result.mappings?.properties.active?.type).toBe('boolean');
190
+ });
191
+ it('should support geo_point field type', () => {
192
+ const result = indexBuilder().mappings({ location: geoPoint() }).build();
193
+ expect(result.mappings?.properties.location?.type).toBe('geo_point');
194
+ });
195
+ it('should support date_range field type', () => {
196
+ const result = indexBuilder().mappings({ availability: dateRange() }).build();
197
+ expect(result.mappings?.properties.availability?.type).toBe('date_range');
198
+ });
199
+ it('should support scaled_float with scaling_factor', () => {
200
+ const result = indexBuilder()
201
+ .mappings({
202
+ score: scaledFloat({ scaling_factor: 100 })
203
+ })
204
+ .build();
205
+ expect(result).toMatchInlineSnapshot(`
206
+ {
207
+ "mappings": {
208
+ "dynamic": "strict",
209
+ "properties": {
210
+ "score": {
211
+ "scaling_factor": 100,
212
+ "type": "scaled_float",
213
+ },
214
+ },
215
+ },
216
+ }
217
+ `);
218
+ });
219
+ it('should support percolator field type', () => {
220
+ const result = indexBuilder().mappings({ query: percolator() }).build();
221
+ expect(result.mappings?.properties.query?.type).toBe('percolator');
222
+ });
223
+ });
224
+ describe('Field mapping properties', () => {
225
+ it('should set boost on a field', () => {
226
+ const result = indexBuilder()
227
+ .mappings({
228
+ name: text({ boost: 2 })
229
+ })
230
+ .build();
231
+ expect(result).toMatchInlineSnapshot(`
232
+ {
233
+ "mappings": {
234
+ "dynamic": "strict",
235
+ "properties": {
236
+ "name": {
237
+ "boost": 2,
238
+ "type": "text",
239
+ },
240
+ },
241
+ },
242
+ }
243
+ `);
244
+ });
245
+ it('should set store and doc_values', () => {
246
+ const result = indexBuilder()
247
+ .mappings({
248
+ asset_class: keyword({ store: true, doc_values: false })
249
+ })
250
+ .build();
251
+ expect(result).toMatchInlineSnapshot(`
252
+ {
253
+ "mappings": {
254
+ "dynamic": "strict",
255
+ "properties": {
256
+ "asset_class": {
257
+ "doc_values": false,
258
+ "store": true,
259
+ "type": "keyword",
260
+ },
261
+ },
262
+ },
263
+ }
264
+ `);
265
+ });
266
+ it('should set index to false', () => {
267
+ const result = indexBuilder()
268
+ .mappings({
269
+ name: text({ index: false })
270
+ })
271
+ .build();
272
+ expect(result).toMatchInlineSnapshot(`
273
+ {
274
+ "mappings": {
275
+ "dynamic": "strict",
276
+ "properties": {
277
+ "name": {
278
+ "index": false,
279
+ "type": "text",
280
+ },
281
+ },
282
+ },
283
+ }
284
+ `);
285
+ });
286
+ });
287
+ describe('Settings', () => {
288
+ it('should build basic settings', () => {
289
+ const result = indexBuilder()
290
+ .settings({
291
+ number_of_shards: 2,
292
+ number_of_replicas: 1
293
+ })
294
+ .build();
295
+ expect(result).toMatchInlineSnapshot(`
296
+ {
297
+ "settings": {
298
+ "number_of_replicas": 1,
299
+ "number_of_shards": 2,
300
+ },
301
+ }
302
+ `);
303
+ });
304
+ it('should configure refresh interval', () => {
305
+ const result = indexBuilder()
306
+ .settings({
307
+ refresh_interval: '30s'
308
+ })
309
+ .build();
310
+ expect(result).toMatchInlineSnapshot(`
311
+ {
312
+ "settings": {
313
+ "refresh_interval": "30s",
314
+ },
315
+ }
316
+ `);
317
+ });
318
+ it('should configure max result window', () => {
319
+ const result = indexBuilder()
320
+ .settings({
321
+ max_result_window: 100000
322
+ })
323
+ .build();
324
+ expect(result).toMatchInlineSnapshot(`
325
+ {
326
+ "settings": {
327
+ "max_result_window": 100000,
328
+ },
329
+ }
330
+ `);
331
+ });
332
+ });
333
+ describe('Aliases', () => {
334
+ it('should add simple alias', () => {
335
+ const result = indexBuilder().alias('products_alias').build();
336
+ expect(result).toMatchInlineSnapshot(`
337
+ {
338
+ "aliases": {
339
+ "products_alias": {},
340
+ },
341
+ }
342
+ `);
343
+ });
344
+ it('should add multiple aliases', () => {
345
+ const result = indexBuilder().alias('products_read').alias('products_write').build();
346
+ expect(result).toMatchInlineSnapshot(`
347
+ {
348
+ "aliases": {
349
+ "products_read": {},
350
+ "products_write": {},
351
+ },
352
+ }
353
+ `);
354
+ });
355
+ it('should add alias with filter', () => {
356
+ const result = indexBuilder()
357
+ .alias('electronics_alias', {
358
+ filter: { term: { category: 'electronics' } }
359
+ })
360
+ .build();
361
+ expect(result).toMatchInlineSnapshot(`
362
+ {
363
+ "aliases": {
364
+ "electronics_alias": {
365
+ "filter": {
366
+ "term": {
367
+ "category": "electronics",
368
+ },
369
+ },
370
+ },
371
+ },
372
+ }
373
+ `);
374
+ });
375
+ it('should add alias with routing', () => {
376
+ const result = indexBuilder().alias('routed_alias', { routing: 'shard-1' }).build();
377
+ expect(result).toMatchInlineSnapshot(`
378
+ {
379
+ "aliases": {
380
+ "routed_alias": {
381
+ "routing": "shard-1",
382
+ },
383
+ },
384
+ }
385
+ `);
386
+ });
387
+ it('should add alias with is_write_index', () => {
388
+ const result = indexBuilder().alias('write_alias', { is_write_index: true }).build();
389
+ expect(result).toMatchInlineSnapshot(`
390
+ {
391
+ "aliases": {
392
+ "write_alias": {
393
+ "is_write_index": true,
394
+ },
395
+ },
396
+ }
397
+ `);
398
+ });
399
+ });
400
+ describe('Complete index configuration', () => {
401
+ it('should combine mappings, settings, and aliases', () => {
402
+ const result = indexBuilder()
403
+ .mappings({
404
+ name: text({ analyzer: 'standard' }),
405
+ market_cap: float(),
406
+ asset_class: keyword(),
407
+ tags: keyword(),
408
+ listed_date: date()
409
+ })
410
+ .settings({
411
+ number_of_shards: 2,
412
+ number_of_replicas: 1,
413
+ refresh_interval: '1s'
414
+ })
415
+ .alias('products_alias')
416
+ .build();
417
+ expect(result).toMatchInlineSnapshot(`
418
+ {
419
+ "aliases": {
420
+ "products_alias": {},
421
+ },
422
+ "mappings": {
423
+ "dynamic": "strict",
424
+ "properties": {
425
+ "asset_class": {
426
+ "type": "keyword",
427
+ },
428
+ "listed_date": {
429
+ "type": "date",
430
+ },
431
+ "market_cap": {
432
+ "type": "float",
433
+ },
434
+ "name": {
435
+ "analyzer": "standard",
436
+ "type": "text",
437
+ },
438
+ "tags": {
439
+ "type": "keyword",
440
+ },
441
+ },
442
+ },
443
+ "settings": {
444
+ "number_of_replicas": 1,
445
+ "number_of_shards": 2,
446
+ "refresh_interval": "1s",
447
+ },
448
+ }
449
+ `);
450
+ });
451
+ });
452
+ describe('Real-world index configurations', () => {
453
+ it('should build e-commerce product index', () => {
454
+ const result = indexBuilder()
455
+ .mappings({
456
+ isin: keyword(),
457
+ name: text({
458
+ analyzer: 'standard',
459
+ fields: {
460
+ keyword: { type: 'keyword' },
461
+ suggest: { type: 'completion' }
462
+ }
463
+ }),
464
+ sector: text({ analyzer: 'english' }),
465
+ market_cap: float(),
466
+ asset_class: keyword(),
467
+ tags: keyword(),
468
+ listed_date: date()
469
+ })
470
+ .settings({
471
+ number_of_shards: 3,
472
+ number_of_replicas: 2,
473
+ refresh_interval: '5s',
474
+ max_result_window: 50000
475
+ })
476
+ .alias('products_live')
477
+ .alias('products_search', {
478
+ filter: { range: { market_cap: { gte: 0 } } }
479
+ })
480
+ .build();
481
+ expect(result).toMatchInlineSnapshot(`
482
+ {
483
+ "aliases": {
484
+ "products_live": {},
485
+ "products_search": {
486
+ "filter": {
487
+ "range": {
488
+ "market_cap": {
489
+ "gte": 0,
490
+ },
491
+ },
492
+ },
493
+ },
494
+ },
495
+ "mappings": {
496
+ "dynamic": "strict",
497
+ "properties": {
498
+ "asset_class": {
499
+ "type": "keyword",
500
+ },
501
+ "isin": {
502
+ "type": "keyword",
503
+ },
504
+ "listed_date": {
505
+ "type": "date",
506
+ },
507
+ "market_cap": {
508
+ "type": "float",
509
+ },
510
+ "name": {
511
+ "analyzer": "standard",
512
+ "fields": {
513
+ "keyword": {
514
+ "type": "keyword",
515
+ },
516
+ "suggest": {
517
+ "type": "completion",
518
+ },
519
+ },
520
+ "type": "text",
521
+ },
522
+ "sector": {
523
+ "analyzer": "english",
524
+ "type": "text",
525
+ },
526
+ "tags": {
527
+ "type": "keyword",
528
+ },
529
+ },
530
+ },
531
+ "settings": {
532
+ "max_result_window": 50000,
533
+ "number_of_replicas": 2,
534
+ "number_of_shards": 3,
535
+ "refresh_interval": "5s",
536
+ },
537
+ }
538
+ `);
539
+ });
540
+ it('should build vector search index', () => {
541
+ const result = indexBuilder()
542
+ .mappings({
543
+ name: text(),
544
+ embedding: denseVector({
545
+ dims: 768,
546
+ index: true,
547
+ index_options: {
548
+ type: 'hnsw',
549
+ m: 16,
550
+ ef_construction: 200
551
+ }
552
+ })
553
+ })
554
+ .settings({
555
+ number_of_shards: 1,
556
+ number_of_replicas: 0
557
+ })
558
+ .build();
559
+ expect(result).toMatchInlineSnapshot(`
560
+ {
561
+ "mappings": {
562
+ "dynamic": "strict",
563
+ "properties": {
564
+ "embedding": {
565
+ "dims": 768,
566
+ "index": true,
567
+ "index_options": {
568
+ "ef_construction": 200,
569
+ "m": 16,
570
+ "type": "hnsw",
571
+ },
572
+ "type": "dense_vector",
573
+ },
574
+ "name": {
575
+ "type": "text",
576
+ },
577
+ },
578
+ },
579
+ "settings": {
580
+ "number_of_replicas": 0,
581
+ "number_of_shards": 1,
582
+ },
583
+ }
584
+ `);
585
+ });
586
+ it('should build time-series index', () => {
587
+ const result = indexBuilder()
588
+ .mappings({
589
+ timestamp: date(),
590
+ level: keyword(),
591
+ message: text(),
592
+ source: keyword()
593
+ })
594
+ .settings({
595
+ number_of_shards: 1,
596
+ number_of_replicas: 1,
597
+ refresh_interval: '30s'
598
+ })
599
+ .alias('logs_current')
600
+ .build();
601
+ expect(result).toMatchInlineSnapshot(`
602
+ {
603
+ "aliases": {
604
+ "logs_current": {},
605
+ },
606
+ "mappings": {
607
+ "dynamic": "strict",
608
+ "properties": {
609
+ "level": {
610
+ "type": "keyword",
611
+ },
612
+ "message": {
613
+ "type": "text",
614
+ },
615
+ "source": {
616
+ "type": "keyword",
617
+ },
618
+ "timestamp": {
619
+ "type": "date",
620
+ },
621
+ },
622
+ },
623
+ "settings": {
624
+ "number_of_replicas": 1,
625
+ "number_of_shards": 1,
626
+ "refresh_interval": "30s",
627
+ },
628
+ }
629
+ `);
630
+ });
631
+ });
632
+ describe('Field helpers', () => {
633
+ it('should resolve field helpers to field mappings', () => {
634
+ const result = indexBuilder().mappings({ name: text(), count: integer() }).build();
635
+ expect(result.mappings?.properties.name).toStrictEqual({ type: 'text' });
636
+ expect(result.mappings?.properties.count).toStrictEqual({
637
+ type: 'integer'
638
+ });
639
+ });
640
+ it('should support helpers called with no options', () => {
641
+ const result = indexBuilder().mappings({ name: text(), price: float(), active: boolean() }).build();
642
+ expect(result.mappings?.properties.name).toStrictEqual({ type: 'text' });
643
+ expect(result.mappings?.properties.price).toStrictEqual({
644
+ type: 'float'
645
+ });
646
+ expect(result.mappings?.properties.active).toStrictEqual({
647
+ type: 'boolean'
648
+ });
649
+ });
650
+ it('should support helpers with and without options', () => {
651
+ const result = indexBuilder()
652
+ .mappings({
653
+ isin: keyword(),
654
+ name: text({ analyzer: 'standard' }),
655
+ market_cap: float(),
656
+ embedding: denseVector({ dims: 384 })
657
+ })
658
+ .build();
659
+ expect(result.mappings?.properties.isin).toStrictEqual({
660
+ type: 'keyword'
661
+ });
662
+ expect(result.mappings?.properties.name).toStrictEqual({
663
+ type: 'text',
664
+ analyzer: 'standard'
665
+ });
666
+ expect(result.mappings?.properties.market_cap).toStrictEqual({
667
+ type: 'float'
668
+ });
669
+ expect(result.mappings?.properties.embedding).toStrictEqual({
670
+ type: 'dense_vector',
671
+ dims: 384
672
+ });
673
+ });
674
+ it('should support all numeric helpers', () => {
675
+ const result = indexBuilder().mappings({ a: long(), b: short(), c: byte(), d: double() }).build();
676
+ expect(result.mappings?.properties.a?.type).toBe('long');
677
+ expect(result.mappings?.properties.b?.type).toBe('short');
678
+ expect(result.mappings?.properties.c?.type).toBe('byte');
679
+ expect(result.mappings?.properties.d?.type).toBe('double');
680
+ });
681
+ it('should support geo and completion helpers', () => {
682
+ const result = indexBuilder()
683
+ .mappings({
684
+ location: geoPoint(),
685
+ suggest: completion({ analyzer: 'simple' })
686
+ })
687
+ .build();
688
+ expect(result.mappings?.properties.location).toStrictEqual({
689
+ type: 'geo_point'
690
+ });
691
+ expect(result.mappings?.properties.suggest).toStrictEqual({
692
+ type: 'completion',
693
+ analyzer: 'simple'
694
+ });
695
+ });
696
+ it('should support date helper with format', () => {
697
+ const result = indexBuilder()
698
+ .mappings({ created: date({ format: 'yyyy-MM-dd' }) })
699
+ .build();
700
+ expect(result.mappings?.properties.created).toStrictEqual({
701
+ type: 'date',
702
+ format: 'yyyy-MM-dd'
703
+ });
704
+ });
705
+ it('should support range type helpers', () => {
706
+ const result = indexBuilder().mappings({ availability: dateRange() }).build();
707
+ expect(result.mappings?.properties.availability).toStrictEqual({
708
+ type: 'date_range'
709
+ });
710
+ });
711
+ it('should support integer helper with options', () => {
712
+ const result = indexBuilder()
713
+ .mappings({ count: integer({ store: true }) })
714
+ .build();
715
+ expect(result.mappings?.properties.count).toStrictEqual({
716
+ type: 'integer',
717
+ store: true
718
+ });
719
+ });
720
+ it('should support halfFloat helper', () => {
721
+ const result = indexBuilder().mappings({ score: halfFloat() }).build();
722
+ expect(result).toMatchInlineSnapshot(`
723
+ {
724
+ "mappings": {
725
+ "dynamic": "strict",
726
+ "properties": {
727
+ "score": {
728
+ "type": "half_float",
729
+ },
730
+ },
731
+ },
732
+ }
733
+ `);
734
+ });
735
+ it('should support halfFloat helper with options', () => {
736
+ const result = indexBuilder()
737
+ .mappings({ score: halfFloat({ index: false }) })
738
+ .build();
739
+ expect(result).toMatchInlineSnapshot(`
740
+ {
741
+ "mappings": {
742
+ "dynamic": "strict",
743
+ "properties": {
744
+ "score": {
745
+ "index": false,
746
+ "type": "half_float",
747
+ },
748
+ },
749
+ },
750
+ }
751
+ `);
752
+ });
753
+ it('should support binary helper', () => {
754
+ const result = indexBuilder().mappings({ blob: binary() }).build();
755
+ expect(result).toMatchInlineSnapshot(`
756
+ {
757
+ "mappings": {
758
+ "dynamic": "strict",
759
+ "properties": {
760
+ "blob": {
761
+ "type": "binary",
762
+ },
763
+ },
764
+ },
765
+ }
766
+ `);
767
+ });
768
+ it('should support ip helper', () => {
769
+ const result = indexBuilder().mappings({ remote_ip: ip() }).build();
770
+ expect(result).toMatchInlineSnapshot(`
771
+ {
772
+ "mappings": {
773
+ "dynamic": "strict",
774
+ "properties": {
775
+ "remote_ip": {
776
+ "type": "ip",
777
+ },
778
+ },
779
+ },
780
+ }
781
+ `);
782
+ });
783
+ it('should support ip helper with options', () => {
784
+ const result = indexBuilder()
785
+ .mappings({ remote_ip: ip({ store: true }) })
786
+ .build();
787
+ expect(result).toMatchInlineSnapshot(`
788
+ {
789
+ "mappings": {
790
+ "dynamic": "strict",
791
+ "properties": {
792
+ "remote_ip": {
793
+ "store": true,
794
+ "type": "ip",
795
+ },
796
+ },
797
+ },
798
+ }
799
+ `);
800
+ });
801
+ it('should support geoShape helper', () => {
802
+ const result = indexBuilder().mappings({ boundary: geoShape() }).build();
803
+ expect(result).toMatchInlineSnapshot(`
804
+ {
805
+ "mappings": {
806
+ "dynamic": "strict",
807
+ "properties": {
808
+ "boundary": {
809
+ "type": "geo_shape",
810
+ },
811
+ },
812
+ },
813
+ }
814
+ `);
815
+ });
816
+ it('should support geoShape helper with options', () => {
817
+ const result = indexBuilder()
818
+ .mappings({ boundary: geoShape({ ignore_malformed: true }) })
819
+ .build();
820
+ expect(result).toMatchInlineSnapshot(`
821
+ {
822
+ "mappings": {
823
+ "dynamic": "strict",
824
+ "properties": {
825
+ "boundary": {
826
+ "ignore_malformed": true,
827
+ "type": "geo_shape",
828
+ },
829
+ },
830
+ },
831
+ }
832
+ `);
833
+ });
834
+ it('should support integerRange helper', () => {
835
+ const result = indexBuilder().mappings({ age_range: integerRange() }).build();
836
+ expect(result).toMatchInlineSnapshot(`
837
+ {
838
+ "mappings": {
839
+ "dynamic": "strict",
840
+ "properties": {
841
+ "age_range": {
842
+ "type": "integer_range",
843
+ },
844
+ },
845
+ },
846
+ }
847
+ `);
848
+ });
849
+ it('should support floatRange helper', () => {
850
+ const result = indexBuilder().mappings({ price_range: floatRange() }).build();
851
+ expect(result).toMatchInlineSnapshot(`
852
+ {
853
+ "mappings": {
854
+ "dynamic": "strict",
855
+ "properties": {
856
+ "price_range": {
857
+ "type": "float_range",
858
+ },
859
+ },
860
+ },
861
+ }
862
+ `);
863
+ });
864
+ it('should support longRange helper', () => {
865
+ const result = indexBuilder().mappings({ timestamp_range: longRange() }).build();
866
+ expect(result).toMatchInlineSnapshot(`
867
+ {
868
+ "mappings": {
869
+ "dynamic": "strict",
870
+ "properties": {
871
+ "timestamp_range": {
872
+ "type": "long_range",
873
+ },
874
+ },
875
+ },
876
+ }
877
+ `);
878
+ });
879
+ it('should support doubleRange helper', () => {
880
+ const result = indexBuilder().mappings({ score_range: doubleRange() }).build();
881
+ expect(result).toMatchInlineSnapshot(`
882
+ {
883
+ "mappings": {
884
+ "dynamic": "strict",
885
+ "properties": {
886
+ "score_range": {
887
+ "type": "double_range",
888
+ },
889
+ },
890
+ },
891
+ }
892
+ `);
893
+ });
894
+ it('should support range helpers with options', () => {
895
+ const result = indexBuilder()
896
+ .mappings({ availability: integerRange({ store: true }) })
897
+ .build();
898
+ expect(result).toMatchInlineSnapshot(`
899
+ {
900
+ "mappings": {
901
+ "dynamic": "strict",
902
+ "properties": {
903
+ "availability": {
904
+ "store": true,
905
+ "type": "integer_range",
906
+ },
907
+ },
908
+ },
909
+ }
910
+ `);
911
+ });
912
+ it('should support object helper with no arguments', () => {
913
+ const result = indexBuilder().mappings({ metadata: object() }).build();
914
+ expect(result).toMatchInlineSnapshot(`
915
+ {
916
+ "mappings": {
917
+ "dynamic": "strict",
918
+ "properties": {
919
+ "metadata": {
920
+ "type": "object",
921
+ },
922
+ },
923
+ },
924
+ }
925
+ `);
926
+ });
927
+ it('should support object helper with fields', () => {
928
+ const result = indexBuilder()
929
+ .mappings({
930
+ address: object({ street: text(), city: keyword() })
931
+ })
932
+ .build();
933
+ expect(result).toMatchInlineSnapshot(`
934
+ {
935
+ "mappings": {
936
+ "dynamic": "strict",
937
+ "properties": {
938
+ "address": {
939
+ "properties": {
940
+ "city": {
941
+ "type": "keyword",
942
+ },
943
+ "street": {
944
+ "type": "text",
945
+ },
946
+ },
947
+ "type": "object",
948
+ },
949
+ },
950
+ },
951
+ }
952
+ `);
953
+ });
954
+ it('should support object helper with enabled: false', () => {
955
+ const result = indexBuilder()
956
+ .mappings({ raw: object(undefined, { enabled: false }) })
957
+ .build();
958
+ expect(result).toMatchInlineSnapshot(`
959
+ {
960
+ "mappings": {
961
+ "dynamic": "strict",
962
+ "properties": {
963
+ "raw": {
964
+ "enabled": false,
965
+ "type": "object",
966
+ },
967
+ },
968
+ },
969
+ }
970
+ `);
971
+ });
972
+ it('should support object helper with fields and enabled option', () => {
973
+ const result = indexBuilder()
974
+ .mappings({
975
+ address: object({ street: text() }, { enabled: true })
976
+ })
977
+ .build();
978
+ expect(result).toMatchInlineSnapshot(`
979
+ {
980
+ "mappings": {
981
+ "dynamic": "strict",
982
+ "properties": {
983
+ "address": {
984
+ "enabled": true,
985
+ "properties": {
986
+ "street": {
987
+ "type": "text",
988
+ },
989
+ },
990
+ "type": "object",
991
+ },
992
+ },
993
+ },
994
+ }
995
+ `);
996
+ });
997
+ it('should support alias helper with path', () => {
998
+ const result = indexBuilder()
999
+ .mappings({ full_name: alias({ path: 'name' }) })
1000
+ .build();
1001
+ expect(result).toMatchInlineSnapshot(`
1002
+ {
1003
+ "mappings": {
1004
+ "dynamic": "strict",
1005
+ "properties": {
1006
+ "full_name": {
1007
+ "path": "name",
1008
+ "type": "alias",
1009
+ },
1010
+ },
1011
+ },
1012
+ }
1013
+ `);
1014
+ });
1015
+ });
1016
+ describe('Undefined field guard', () => {
1017
+ it('should skip fields with undefined values in mappings', () => {
1018
+ const result = indexBuilder()
1019
+ .mappings({
1020
+ name: text(),
1021
+ price: undefined
1022
+ })
1023
+ .build();
1024
+ expect(result).toMatchInlineSnapshot(`
1025
+ {
1026
+ "mappings": {
1027
+ "dynamic": "strict",
1028
+ "properties": {
1029
+ "name": {
1030
+ "type": "text",
1031
+ },
1032
+ },
1033
+ },
1034
+ }
1035
+ `);
1036
+ });
1037
+ });
1038
+ describe('Mapping options (dynamic, _source, _meta)', () => {
1039
+ it('should default to dynamic strict when using mappings() factory', () => {
1040
+ const schema = mappings({ name: text() });
1041
+ const result = indexBuilder().mappings(schema).build();
1042
+ expect(result).toMatchInlineSnapshot(`
1043
+ {
1044
+ "mappings": {
1045
+ "dynamic": "strict",
1046
+ "properties": {
1047
+ "name": {
1048
+ "type": "text",
1049
+ },
1050
+ },
1051
+ },
1052
+ }
1053
+ `);
1054
+ });
1055
+ it('should allow overriding dynamic to true', () => {
1056
+ const schema = mappings({ name: text() }, { dynamic: true });
1057
+ const result = indexBuilder().mappings(schema).build();
1058
+ expect(result).toMatchInlineSnapshot(`
1059
+ {
1060
+ "mappings": {
1061
+ "dynamic": true,
1062
+ "properties": {
1063
+ "name": {
1064
+ "type": "text",
1065
+ },
1066
+ },
1067
+ },
1068
+ }
1069
+ `);
1070
+ });
1071
+ it('should allow overriding dynamic to runtime', () => {
1072
+ const schema = mappings({ name: text() }, { dynamic: 'runtime' });
1073
+ const result = indexBuilder().mappings(schema).build();
1074
+ expect(result).toMatchInlineSnapshot(`
1075
+ {
1076
+ "mappings": {
1077
+ "dynamic": "runtime",
1078
+ "properties": {
1079
+ "name": {
1080
+ "type": "text",
1081
+ },
1082
+ },
1083
+ },
1084
+ }
1085
+ `);
1086
+ });
1087
+ it('should default to dynamic strict for inline mappings (raw fields)', () => {
1088
+ const result = indexBuilder().mappings({ name: text() }).build();
1089
+ expect(result).toMatchInlineSnapshot(`
1090
+ {
1091
+ "mappings": {
1092
+ "dynamic": "strict",
1093
+ "properties": {
1094
+ "name": {
1095
+ "type": "text",
1096
+ },
1097
+ },
1098
+ },
1099
+ }
1100
+ `);
1101
+ });
1102
+ it('should allow overriding dynamic on inline mappings via options', () => {
1103
+ const result = indexBuilder().mappings({ name: text() }, { dynamic: true }).build();
1104
+ expect(result).toMatchInlineSnapshot(`
1105
+ {
1106
+ "mappings": {
1107
+ "dynamic": true,
1108
+ "properties": {
1109
+ "name": {
1110
+ "type": "text",
1111
+ },
1112
+ },
1113
+ },
1114
+ }
1115
+ `);
1116
+ });
1117
+ it('should allow _source and _meta on inline mappings via options', () => {
1118
+ const result = indexBuilder()
1119
+ .mappings({ name: text(), embedding: denseVector({ dims: 384 }) }, { _source: { excludes: ['embedding'] }, _meta: { version: 2 } })
1120
+ .build();
1121
+ expect(result).toMatchInlineSnapshot(`
1122
+ {
1123
+ "mappings": {
1124
+ "_meta": {
1125
+ "version": 2,
1126
+ },
1127
+ "_source": {
1128
+ "excludes": [
1129
+ "embedding",
1130
+ ],
1131
+ },
1132
+ "dynamic": "strict",
1133
+ "properties": {
1134
+ "embedding": {
1135
+ "dims": 384,
1136
+ "type": "dense_vector",
1137
+ },
1138
+ "name": {
1139
+ "type": "text",
1140
+ },
1141
+ },
1142
+ },
1143
+ }
1144
+ `);
1145
+ });
1146
+ it('should allow inline options to override schema options', () => {
1147
+ const schema = mappings({ name: text() }, { dynamic: 'strict', _meta: { version: 1 } });
1148
+ const result = indexBuilder()
1149
+ .mappings(schema, { _meta: { version: 2 } })
1150
+ .build();
1151
+ expect(result).toMatchInlineSnapshot(`
1152
+ {
1153
+ "mappings": {
1154
+ "_meta": {
1155
+ "version": 2,
1156
+ },
1157
+ "dynamic": "strict",
1158
+ "properties": {
1159
+ "name": {
1160
+ "type": "text",
1161
+ },
1162
+ },
1163
+ },
1164
+ }
1165
+ `);
1166
+ });
1167
+ it('should pass _source excludes through to index mappings', () => {
1168
+ const schema = mappings({ title: text(), embedding: denseVector({ dims: 768 }) }, { _source: { excludes: ['embedding'] } });
1169
+ const result = indexBuilder().mappings(schema).build();
1170
+ expect(result).toMatchInlineSnapshot(`
1171
+ {
1172
+ "mappings": {
1173
+ "_source": {
1174
+ "excludes": [
1175
+ "embedding",
1176
+ ],
1177
+ },
1178
+ "dynamic": "strict",
1179
+ "properties": {
1180
+ "embedding": {
1181
+ "dims": 768,
1182
+ "type": "dense_vector",
1183
+ },
1184
+ "title": {
1185
+ "type": "text",
1186
+ },
1187
+ },
1188
+ },
1189
+ }
1190
+ `);
1191
+ });
1192
+ it('should pass _source includes through to index mappings', () => {
1193
+ const schema = mappings({ title: text(), body: text(), tags: keyword() }, { _source: { includes: ['title', 'tags'] } });
1194
+ const result = indexBuilder().mappings(schema).build();
1195
+ expect(result).toMatchInlineSnapshot(`
1196
+ {
1197
+ "mappings": {
1198
+ "_source": {
1199
+ "includes": [
1200
+ "title",
1201
+ "tags",
1202
+ ],
1203
+ },
1204
+ "dynamic": "strict",
1205
+ "properties": {
1206
+ "body": {
1207
+ "type": "text",
1208
+ },
1209
+ "tags": {
1210
+ "type": "keyword",
1211
+ },
1212
+ "title": {
1213
+ "type": "text",
1214
+ },
1215
+ },
1216
+ },
1217
+ }
1218
+ `);
1219
+ });
1220
+ it('should pass _meta through to index mappings', () => {
1221
+ const schema = mappings({ name: text() }, { _meta: { version: '1.0', created_by: 'elasticlink' } });
1222
+ const result = indexBuilder().mappings(schema).build();
1223
+ expect(result).toMatchInlineSnapshot(`
1224
+ {
1225
+ "mappings": {
1226
+ "_meta": {
1227
+ "created_by": "elasticlink",
1228
+ "version": "1.0",
1229
+ },
1230
+ "dynamic": "strict",
1231
+ "properties": {
1232
+ "name": {
1233
+ "type": "text",
1234
+ },
1235
+ },
1236
+ },
1237
+ }
1238
+ `);
1239
+ });
1240
+ });
1241
+ describe('New field-level options', () => {
1242
+ it('should support copy_to on text fields', () => {
1243
+ const result = indexBuilder()
1244
+ .mappings({
1245
+ title: text({ copy_to: 'searchable' }),
1246
+ body: text({ copy_to: ['searchable', 'all_text'] })
1247
+ })
1248
+ .build();
1249
+ expect(result).toMatchInlineSnapshot(`
1250
+ {
1251
+ "mappings": {
1252
+ "dynamic": "strict",
1253
+ "properties": {
1254
+ "body": {
1255
+ "copy_to": [
1256
+ "searchable",
1257
+ "all_text",
1258
+ ],
1259
+ "type": "text",
1260
+ },
1261
+ "title": {
1262
+ "copy_to": "searchable",
1263
+ "type": "text",
1264
+ },
1265
+ },
1266
+ },
1267
+ }
1268
+ `);
1269
+ });
1270
+ it('should support index_prefixes and index_phrases on text fields', () => {
1271
+ const result = indexBuilder()
1272
+ .mappings({
1273
+ name: text({
1274
+ index_prefixes: { min_chars: 2, max_chars: 5 },
1275
+ index_phrases: true
1276
+ })
1277
+ })
1278
+ .build();
1279
+ expect(result).toMatchInlineSnapshot(`
1280
+ {
1281
+ "mappings": {
1282
+ "dynamic": "strict",
1283
+ "properties": {
1284
+ "name": {
1285
+ "index_phrases": true,
1286
+ "index_prefixes": {
1287
+ "max_chars": 5,
1288
+ "min_chars": 2,
1289
+ },
1290
+ "type": "text",
1291
+ },
1292
+ },
1293
+ },
1294
+ }
1295
+ `);
1296
+ });
1297
+ it('should support eager_global_ordinals on keyword fields', () => {
1298
+ const result = indexBuilder()
1299
+ .mappings({ status: keyword({ eager_global_ordinals: true }) })
1300
+ .build();
1301
+ expect(result).toMatchInlineSnapshot(`
1302
+ {
1303
+ "mappings": {
1304
+ "dynamic": "strict",
1305
+ "properties": {
1306
+ "status": {
1307
+ "eager_global_ordinals": true,
1308
+ "type": "keyword",
1309
+ },
1310
+ },
1311
+ },
1312
+ }
1313
+ `);
1314
+ });
1315
+ it('should support null_value on keyword fields', () => {
1316
+ const result = indexBuilder()
1317
+ .mappings({ status: keyword({ null_value: 'UNKNOWN' }) })
1318
+ .build();
1319
+ expect(result).toMatchInlineSnapshot(`
1320
+ {
1321
+ "mappings": {
1322
+ "dynamic": "strict",
1323
+ "properties": {
1324
+ "status": {
1325
+ "null_value": "UNKNOWN",
1326
+ "type": "keyword",
1327
+ },
1328
+ },
1329
+ },
1330
+ }
1331
+ `);
1332
+ });
1333
+ it('should support ignore_malformed on numeric fields', () => {
1334
+ const result = indexBuilder()
1335
+ .mappings({ price: float({ ignore_malformed: true }) })
1336
+ .build();
1337
+ expect(result).toMatchInlineSnapshot(`
1338
+ {
1339
+ "mappings": {
1340
+ "dynamic": "strict",
1341
+ "properties": {
1342
+ "price": {
1343
+ "ignore_malformed": true,
1344
+ "type": "float",
1345
+ },
1346
+ },
1347
+ },
1348
+ }
1349
+ `);
1350
+ });
1351
+ it('should support ignore_malformed on date fields', () => {
1352
+ const result = indexBuilder()
1353
+ .mappings({ created: date({ ignore_malformed: true }) })
1354
+ .build();
1355
+ expect(result).toMatchInlineSnapshot(`
1356
+ {
1357
+ "mappings": {
1358
+ "dynamic": "strict",
1359
+ "properties": {
1360
+ "created": {
1361
+ "ignore_malformed": true,
1362
+ "type": "date",
1363
+ },
1364
+ },
1365
+ },
1366
+ }
1367
+ `);
1368
+ });
1369
+ it('should support ignore_malformed on geo_point fields', () => {
1370
+ const result = indexBuilder()
1371
+ .mappings({ location: geoPoint({ ignore_malformed: true }) })
1372
+ .build();
1373
+ expect(result).toMatchInlineSnapshot(`
1374
+ {
1375
+ "mappings": {
1376
+ "dynamic": "strict",
1377
+ "properties": {
1378
+ "location": {
1379
+ "ignore_malformed": true,
1380
+ "type": "geo_point",
1381
+ },
1382
+ },
1383
+ },
1384
+ }
1385
+ `);
1386
+ });
1387
+ it('should support ignore_malformed on ip fields', () => {
1388
+ const result = indexBuilder()
1389
+ .mappings({ addr: ip({ ignore_malformed: true }) })
1390
+ .build();
1391
+ expect(result).toMatchInlineSnapshot(`
1392
+ {
1393
+ "mappings": {
1394
+ "dynamic": "strict",
1395
+ "properties": {
1396
+ "addr": {
1397
+ "ignore_malformed": true,
1398
+ "type": "ip",
1399
+ },
1400
+ },
1401
+ },
1402
+ }
1403
+ `);
1404
+ });
1405
+ it('should support term_vector on text fields', () => {
1406
+ const result = indexBuilder()
1407
+ .mappings({
1408
+ content: text({ term_vector: 'with_positions_offsets' })
1409
+ })
1410
+ .build();
1411
+ expect(result).toMatchInlineSnapshot(`
1412
+ {
1413
+ "mappings": {
1414
+ "dynamic": "strict",
1415
+ "properties": {
1416
+ "content": {
1417
+ "term_vector": "with_positions_offsets",
1418
+ "type": "text",
1419
+ },
1420
+ },
1421
+ },
1422
+ }
1423
+ `);
1424
+ });
1425
+ it('should support null_value on numeric fields', () => {
1426
+ const result = indexBuilder()
1427
+ .mappings({ count: integer({ null_value: 0 }) })
1428
+ .build();
1429
+ expect(result).toMatchInlineSnapshot(`
1430
+ {
1431
+ "mappings": {
1432
+ "dynamic": "strict",
1433
+ "properties": {
1434
+ "count": {
1435
+ "null_value": 0,
1436
+ "type": "integer",
1437
+ },
1438
+ },
1439
+ },
1440
+ }
1441
+ `);
1442
+ });
1443
+ it('should support ignore_above on keyword fields', () => {
1444
+ const result = indexBuilder()
1445
+ .mappings({ tag: keyword({ ignore_above: 256 }) })
1446
+ .build();
1447
+ expect(result).toMatchInlineSnapshot(`
1448
+ {
1449
+ "mappings": {
1450
+ "dynamic": "strict",
1451
+ "properties": {
1452
+ "tag": {
1453
+ "ignore_above": 256,
1454
+ "type": "keyword",
1455
+ },
1456
+ },
1457
+ },
1458
+ }
1459
+ `);
1460
+ });
1461
+ });
1462
+ describe('New field types', () => {
1463
+ it('should support matchOnlyText helper', () => {
1464
+ const result = indexBuilder().mappings({ log_message: matchOnlyText() }).build();
1465
+ expect(result).toMatchInlineSnapshot(`
1466
+ {
1467
+ "mappings": {
1468
+ "dynamic": "strict",
1469
+ "properties": {
1470
+ "log_message": {
1471
+ "type": "match_only_text",
1472
+ },
1473
+ },
1474
+ },
1475
+ }
1476
+ `);
1477
+ });
1478
+ it('should support matchOnlyText helper with options', () => {
1479
+ const result = indexBuilder()
1480
+ .mappings({
1481
+ log_message: matchOnlyText({
1482
+ copy_to: 'searchable'
1483
+ })
1484
+ })
1485
+ .build();
1486
+ expect(result).toMatchInlineSnapshot(`
1487
+ {
1488
+ "mappings": {
1489
+ "dynamic": "strict",
1490
+ "properties": {
1491
+ "log_message": {
1492
+ "copy_to": "searchable",
1493
+ "type": "match_only_text",
1494
+ },
1495
+ },
1496
+ },
1497
+ }
1498
+ `);
1499
+ });
1500
+ it('should support searchAsYouType helper', () => {
1501
+ const result = indexBuilder().mappings({ name: searchAsYouType() }).build();
1502
+ expect(result).toMatchInlineSnapshot(`
1503
+ {
1504
+ "mappings": {
1505
+ "dynamic": "strict",
1506
+ "properties": {
1507
+ "name": {
1508
+ "type": "search_as_you_type",
1509
+ },
1510
+ },
1511
+ },
1512
+ }
1513
+ `);
1514
+ });
1515
+ it('should support searchAsYouType helper with options', () => {
1516
+ const result = indexBuilder()
1517
+ .mappings({
1518
+ name: searchAsYouType({
1519
+ analyzer: 'standard',
1520
+ max_shingle_size: 4
1521
+ })
1522
+ })
1523
+ .build();
1524
+ expect(result).toMatchInlineSnapshot(`
1525
+ {
1526
+ "mappings": {
1527
+ "dynamic": "strict",
1528
+ "properties": {
1529
+ "name": {
1530
+ "analyzer": "standard",
1531
+ "max_shingle_size": 4,
1532
+ "type": "search_as_you_type",
1533
+ },
1534
+ },
1535
+ },
1536
+ }
1537
+ `);
1538
+ });
1539
+ it('should support constantKeyword helper', () => {
1540
+ const result = indexBuilder()
1541
+ .mappings({ doc_type: constantKeyword({ value: 'product' }) })
1542
+ .build();
1543
+ expect(result).toMatchInlineSnapshot(`
1544
+ {
1545
+ "mappings": {
1546
+ "dynamic": "strict",
1547
+ "properties": {
1548
+ "doc_type": {
1549
+ "type": "constant_keyword",
1550
+ "value": "product",
1551
+ },
1552
+ },
1553
+ },
1554
+ }
1555
+ `);
1556
+ });
1557
+ it('should support wildcardField helper', () => {
1558
+ const result = indexBuilder().mappings({ path: wildcardField() }).build();
1559
+ expect(result).toMatchInlineSnapshot(`
1560
+ {
1561
+ "mappings": {
1562
+ "dynamic": "strict",
1563
+ "properties": {
1564
+ "path": {
1565
+ "type": "wildcard",
1566
+ },
1567
+ },
1568
+ },
1569
+ }
1570
+ `);
1571
+ });
1572
+ it('should support wildcardField helper with options', () => {
1573
+ const result = indexBuilder()
1574
+ .mappings({ path: wildcardField({ ignore_above: 512 }) })
1575
+ .build();
1576
+ expect(result).toMatchInlineSnapshot(`
1577
+ {
1578
+ "mappings": {
1579
+ "dynamic": "strict",
1580
+ "properties": {
1581
+ "path": {
1582
+ "ignore_above": 512,
1583
+ "type": "wildcard",
1584
+ },
1585
+ },
1586
+ },
1587
+ }
1588
+ `);
1589
+ });
1590
+ it('should support flattened helper', () => {
1591
+ const result = indexBuilder().mappings({ labels: flattened() }).build();
1592
+ expect(result).toMatchInlineSnapshot(`
1593
+ {
1594
+ "mappings": {
1595
+ "dynamic": "strict",
1596
+ "properties": {
1597
+ "labels": {
1598
+ "type": "flattened",
1599
+ },
1600
+ },
1601
+ },
1602
+ }
1603
+ `);
1604
+ });
1605
+ it('should support flattened helper with options', () => {
1606
+ const result = indexBuilder()
1607
+ .mappings({
1608
+ metadata: flattened({ depth_limit: 3, eager_global_ordinals: true })
1609
+ })
1610
+ .build();
1611
+ expect(result).toMatchInlineSnapshot(`
1612
+ {
1613
+ "mappings": {
1614
+ "dynamic": "strict",
1615
+ "properties": {
1616
+ "metadata": {
1617
+ "depth_limit": 3,
1618
+ "eager_global_ordinals": true,
1619
+ "type": "flattened",
1620
+ },
1621
+ },
1622
+ },
1623
+ }
1624
+ `);
1625
+ });
1626
+ it('should support quantizedDenseVector helper', () => {
1627
+ const result = indexBuilder()
1628
+ .mappings({
1629
+ embedding: quantizedDenseVector({ dims: 768, similarity: 'cosine' })
1630
+ })
1631
+ .build();
1632
+ expect(result).toMatchInlineSnapshot(`
1633
+ {
1634
+ "mappings": {
1635
+ "dynamic": "strict",
1636
+ "properties": {
1637
+ "embedding": {
1638
+ "dims": 768,
1639
+ "index_options": {
1640
+ "type": "int8_hnsw",
1641
+ },
1642
+ "similarity": "cosine",
1643
+ "type": "dense_vector",
1644
+ },
1645
+ },
1646
+ },
1647
+ }
1648
+ `);
1649
+ });
1650
+ it('should support quantizedDenseVector with custom index_options', () => {
1651
+ const result = indexBuilder()
1652
+ .mappings({
1653
+ embedding: quantizedDenseVector({
1654
+ dims: 384,
1655
+ similarity: 'dot_product',
1656
+ index_options: { type: 'int8_hnsw', m: 32, ef_construction: 200 }
1657
+ })
1658
+ })
1659
+ .build();
1660
+ expect(result).toMatchInlineSnapshot(`
1661
+ {
1662
+ "mappings": {
1663
+ "dynamic": "strict",
1664
+ "properties": {
1665
+ "embedding": {
1666
+ "dims": 384,
1667
+ "index_options": {
1668
+ "ef_construction": 200,
1669
+ "m": 32,
1670
+ "type": "int8_hnsw",
1671
+ },
1672
+ "similarity": "dot_product",
1673
+ "type": "dense_vector",
1674
+ },
1675
+ },
1676
+ },
1677
+ }
1678
+ `);
1679
+ });
1680
+ it('should support quantizedDenseVector with no options', () => {
1681
+ const result = indexBuilder().mappings({ embedding: quantizedDenseVector() }).build();
1682
+ expect(result).toMatchInlineSnapshot(`
1683
+ {
1684
+ "mappings": {
1685
+ "dynamic": "strict",
1686
+ "properties": {
1687
+ "embedding": {
1688
+ "index_options": {
1689
+ "type": "int8_hnsw",
1690
+ },
1691
+ "type": "dense_vector",
1692
+ },
1693
+ },
1694
+ },
1695
+ }
1696
+ `);
1697
+ });
1698
+ });
1699
+ });