@travetto/model-elasticsearch 6.0.0-rc.1 → 6.0.0-rc.3
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/README.md +10 -18
- package/__index__.ts +2 -2
- package/package.json +6 -6
- package/src/config.ts +1 -1
- package/src/index-manager.ts +3 -4
- package/src/internal/query.ts +3 -6
- package/src/internal/schema.ts +5 -4
- package/src/service.ts +41 -48
package/README.md
CHANGED
|
@@ -13,17 +13,18 @@ npm install @travetto/model-elasticsearch
|
|
|
13
13
|
yarn add @travetto/model-elasticsearch
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
This module provides an [elasticsearch](https://elastic.co)-based implementation of the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations."). This source allows the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") module to read, write and query against [elasticsearch](https://elastic.co). In development mode, [ElasticsearchModelService](https://github.com/travetto/travetto/tree/main/module/model-elasticsearch/src/service.ts#
|
|
16
|
+
This module provides an [elasticsearch](https://elastic.co)-based implementation of the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations."). This source allows the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") module to read, write and query against [elasticsearch](https://elastic.co). In development mode, [ElasticsearchModelService](https://github.com/travetto/travetto/tree/main/module/model-elasticsearch/src/service.ts#L30) will also modify the [elasticsearch](https://elastic.co) schema in real time to minimize impact to development.
|
|
17
17
|
|
|
18
18
|
Supported features:
|
|
19
|
-
* [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/
|
|
20
|
-
* [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/
|
|
21
|
-
* [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/
|
|
22
|
-
* [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/
|
|
23
|
-
* [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/
|
|
24
|
-
* [Facet](https://github.com/travetto/travetto/tree/main/module/model-query/src/
|
|
25
|
-
* [Query](https://github.com/travetto/travetto/tree/main/module/model-query/src/
|
|
26
|
-
* [Suggest](https://github.com/travetto/travetto/tree/main/module/model-query/src/
|
|
19
|
+
* [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/types/crud.ts#L11)
|
|
20
|
+
* [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/types/bulk.ts#L64)
|
|
21
|
+
* [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/types/expiry.ts#L10)
|
|
22
|
+
* [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/types/indexed.ts#L11)
|
|
23
|
+
* [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/crud.ts#L11)
|
|
24
|
+
* [Facet](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/facet.ts#L14)
|
|
25
|
+
* [Query](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/query.ts#L10)
|
|
26
|
+
* [Suggest](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/suggest.ts#L12)
|
|
27
|
+
|
|
27
28
|
Out of the box, by installing the module, everything should be wired up by default.If you need to customize any aspect of the source or config, you can override and register it with the [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support.") module.
|
|
28
29
|
|
|
29
30
|
**Code: Wiring up a custom Model Source**
|
|
@@ -45,15 +46,6 @@ where the [ElasticsearchModelConfig](https://github.com/travetto/travetto/tree/m
|
|
|
45
46
|
|
|
46
47
|
**Code: Structure of ElasticsearchModelConfig**
|
|
47
48
|
```typescript
|
|
48
|
-
import { TimeSpan } from '@travetto/runtime';
|
|
49
|
-
import { Config } from '@travetto/config';
|
|
50
|
-
import { Field } from '@travetto/schema';
|
|
51
|
-
|
|
52
|
-
import { EsSchemaConfig } from './internal/types';
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Elasticsearch model config
|
|
56
|
-
*/
|
|
57
49
|
@Config('model.elasticsearch')
|
|
58
50
|
export class ElasticsearchModelConfig {
|
|
59
51
|
/**
|
package/__index__.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './src/config';
|
|
2
|
-
export * from './src/service';
|
|
1
|
+
export * from './src/config.ts';
|
|
2
|
+
export * from './src/service.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-elasticsearch",
|
|
3
|
-
"version": "6.0.0-rc.
|
|
3
|
+
"version": "6.0.0-rc.3",
|
|
4
4
|
"description": "Elasticsearch backing for the travetto model module, with real-time modeling support for Elasticsearch mappings.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"elasticsearch",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"directory": "module/model-elasticsearch"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@elastic/elasticsearch": "^8.
|
|
31
|
-
"@travetto/cli": "^6.0.0-rc.
|
|
32
|
-
"@travetto/config": "^6.0.0-rc.
|
|
33
|
-
"@travetto/model": "^6.0.0-rc.
|
|
34
|
-
"@travetto/model-query": "^6.0.0-rc.
|
|
30
|
+
"@elastic/elasticsearch": "^8.18.1",
|
|
31
|
+
"@travetto/cli": "^6.0.0-rc.3",
|
|
32
|
+
"@travetto/config": "^6.0.0-rc.2",
|
|
33
|
+
"@travetto/model": "^6.0.0-rc.2",
|
|
34
|
+
"@travetto/model-query": "^6.0.0-rc.2"
|
|
35
35
|
},
|
|
36
36
|
"travetto": {
|
|
37
37
|
"displayName": "Elasticsearch Model Source"
|
package/src/config.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { TimeSpan } from '@travetto/runtime';
|
|
|
2
2
|
import { Config } from '@travetto/config';
|
|
3
3
|
import { Field } from '@travetto/schema';
|
|
4
4
|
|
|
5
|
-
import { EsSchemaConfig } from './internal/types';
|
|
5
|
+
import { EsSchemaConfig } from './internal/types.ts';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Elasticsearch model config
|
package/src/index-manager.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Client, estypes } from '@elastic/elasticsearch';
|
|
2
2
|
|
|
3
3
|
import { Class } from '@travetto/runtime';
|
|
4
|
-
import { ModelRegistry, ModelType } from '@travetto/model';
|
|
5
|
-
import { ModelStorageSupport } from '@travetto/model/src/service/storage';
|
|
4
|
+
import { ModelRegistry, ModelType, ModelStorageSupport } from '@travetto/model';
|
|
6
5
|
import { SchemaChange } from '@travetto/schema';
|
|
7
6
|
|
|
8
|
-
import { ElasticsearchModelConfig } from './config';
|
|
9
|
-
import { ElasticsearchSchemaUtil } from './internal/schema';
|
|
7
|
+
import { ElasticsearchModelConfig } from './config.ts';
|
|
8
|
+
import { ElasticsearchSchemaUtil } from './internal/schema.ts';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Manager for elasticsearch indices and schemas
|
package/src/internal/query.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { estypes } from '@elastic/elasticsearch';
|
|
2
2
|
|
|
3
3
|
import { castTo, Class, TypedObject } from '@travetto/runtime';
|
|
4
|
-
import { WhereClause, SelectClause, SortClause, Query } from '@travetto/model-query';
|
|
5
|
-
import {
|
|
6
|
-
import { ModelRegistry } from '@travetto/model/src/registry/model';
|
|
7
|
-
import { IndexConfig } from '@travetto/model/src/registry/types';
|
|
8
|
-
import { ModelType } from '@travetto/model/src/types/model';
|
|
4
|
+
import { WhereClause, SelectClause, SortClause, Query, ModelQueryUtil } from '@travetto/model-query';
|
|
5
|
+
import { IndexConfig, ModelType, ModelRegistry } from '@travetto/model';
|
|
9
6
|
import { DataUtil, SchemaRegistry } from '@travetto/schema';
|
|
10
7
|
|
|
11
|
-
import { EsSchemaConfig } from './types';
|
|
8
|
+
import { EsSchemaConfig } from './types.ts';
|
|
12
9
|
|
|
13
10
|
/**
|
|
14
11
|
* Support tools for dealing with elasticsearch specific requirements
|
package/src/internal/schema.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { estypes } from '@elastic/elasticsearch';
|
|
2
2
|
|
|
3
|
-
import { Class } from '@travetto/runtime';
|
|
3
|
+
import { Class, toConcrete } from '@travetto/runtime';
|
|
4
4
|
import { ModelRegistry } from '@travetto/model';
|
|
5
|
-
import {
|
|
6
|
-
import { DataUtil, SchemaRegistry } from '@travetto/schema';
|
|
5
|
+
import { Point, DataUtil, SchemaRegistry } from '@travetto/schema';
|
|
7
6
|
|
|
8
|
-
import { EsSchemaConfig } from './types';
|
|
7
|
+
import { EsSchemaConfig } from './types.ts';
|
|
8
|
+
|
|
9
|
+
const PointImpl = toConcrete<Point>();
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Utils for ES Schema management
|
package/src/service.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { Client, errors, estypes } from '@elastic/elasticsearch';
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ModelCrudSupport, BulkOp, BulkResponse, ModelBulkSupport, ModelExpirySupport,
|
|
5
|
-
ModelIndexedSupport, ModelType, ModelStorageSupport, NotFoundError, ModelRegistry,
|
|
6
|
-
|
|
5
|
+
ModelIndexedSupport, ModelType, ModelStorageSupport, NotFoundError, ModelRegistry, OptionalId,
|
|
6
|
+
ModelCrudUtil, ModelIndexedUtil, ModelStorageUtil, ModelExpiryUtil, ModelBulkUtil
|
|
7
7
|
} from '@travetto/model';
|
|
8
8
|
import { ShutdownManager, type DeepPartial, type Class, castTo, asFull, TypedObject, asConstructable } from '@travetto/runtime';
|
|
9
9
|
import { SchemaChange, BindUtil } from '@travetto/schema';
|
|
@@ -11,24 +11,17 @@ import { Injectable } from '@travetto/di';
|
|
|
11
11
|
import {
|
|
12
12
|
ModelQuery, ModelQueryCrudSupport, ModelQueryFacetSupport,
|
|
13
13
|
ModelQuerySupport, PageableModelQuery, Query, ValidStringFields,
|
|
14
|
-
QueryVerifier
|
|
14
|
+
QueryVerifier, ModelQuerySuggestSupport,
|
|
15
|
+
ModelQueryUtil, ModelQuerySuggestUtil, ModelQueryCrudUtil,
|
|
16
|
+
ModelQueryFacet,
|
|
15
17
|
} from '@travetto/model-query';
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { ModelQueryExpiryUtil } from '@travetto/model-query/src/internal/service/expiry';
|
|
24
|
-
import { ModelQuerySuggestSupport } from '@travetto/model-query/src/service/suggest';
|
|
25
|
-
import { ModelBulkUtil } from '@travetto/model/src/internal/service/bulk';
|
|
26
|
-
|
|
27
|
-
import { ElasticsearchModelConfig } from './config';
|
|
28
|
-
import { EsBulkError } from './internal/types';
|
|
29
|
-
import { ElasticsearchQueryUtil } from './internal/query';
|
|
30
|
-
import { ElasticsearchSchemaUtil } from './internal/schema';
|
|
31
|
-
import { IndexManager } from './index-manager';
|
|
19
|
+
|
|
20
|
+
import { ElasticsearchModelConfig } from './config.ts';
|
|
21
|
+
import { EsBulkError } from './internal/types.ts';
|
|
22
|
+
import { ElasticsearchQueryUtil } from './internal/query.ts';
|
|
23
|
+
import { ElasticsearchSchemaUtil } from './internal/schema.ts';
|
|
24
|
+
import { IndexManager } from './index-manager.ts';
|
|
32
25
|
|
|
33
26
|
/**
|
|
34
27
|
* Elasticsearch model source.
|
|
@@ -57,12 +50,12 @@ export class ElasticsearchModelService implements
|
|
|
57
50
|
query = undefined;
|
|
58
51
|
}
|
|
59
52
|
try {
|
|
60
|
-
const
|
|
53
|
+
const result = await this.client.search<T>({
|
|
61
54
|
...this.manager.getIdentity(cls),
|
|
62
55
|
...search,
|
|
63
56
|
query
|
|
64
57
|
});
|
|
65
|
-
return
|
|
58
|
+
return result;
|
|
66
59
|
} catch (err) {
|
|
67
60
|
if (err instanceof errors.ResponseError && err.meta.body && typeof err.meta.body === 'object' && 'error' in err.meta.body) {
|
|
68
61
|
console.error(err.meta.body.error);
|
|
@@ -138,8 +131,8 @@ export class ElasticsearchModelService implements
|
|
|
138
131
|
|
|
139
132
|
async get<T extends ModelType>(cls: Class<T>, id: string): Promise<T> {
|
|
140
133
|
try {
|
|
141
|
-
const
|
|
142
|
-
return this.postLoad(cls,
|
|
134
|
+
const result = await this.client.get<T>({ ...this.manager.getIdentity(cls), id });
|
|
135
|
+
return this.postLoad(cls, result);
|
|
143
136
|
} catch {
|
|
144
137
|
throw new NotFoundError(cls, id);
|
|
145
138
|
}
|
|
@@ -149,12 +142,12 @@ export class ElasticsearchModelService implements
|
|
|
149
142
|
ModelCrudUtil.ensureNotSubType(cls);
|
|
150
143
|
|
|
151
144
|
try {
|
|
152
|
-
const
|
|
145
|
+
const result = await this.client.delete({
|
|
153
146
|
...this.manager.getIdentity(cls),
|
|
154
147
|
id,
|
|
155
148
|
refresh: true,
|
|
156
149
|
});
|
|
157
|
-
if (
|
|
150
|
+
if (result.result === 'not_found') {
|
|
158
151
|
throw new NotFoundError(cls, id);
|
|
159
152
|
}
|
|
160
153
|
} catch (err) {
|
|
@@ -299,7 +292,7 @@ export class ElasticsearchModelService implements
|
|
|
299
292
|
return acc;
|
|
300
293
|
}, []);
|
|
301
294
|
|
|
302
|
-
const
|
|
295
|
+
const result = await this.client.bulk({
|
|
303
296
|
operations: body,
|
|
304
297
|
refresh: true
|
|
305
298
|
});
|
|
@@ -318,8 +311,8 @@ export class ElasticsearchModelService implements
|
|
|
318
311
|
|
|
319
312
|
type Count = keyof typeof out['counts'];
|
|
320
313
|
|
|
321
|
-
for (let i = 0; i <
|
|
322
|
-
const item =
|
|
314
|
+
for (let i = 0; i < result.items.length; i++) {
|
|
315
|
+
const item = result.items[i];
|
|
323
316
|
const [k] = TypedObject.keys(item);
|
|
324
317
|
const v = item[k]!;
|
|
325
318
|
if (v.error) {
|
|
@@ -353,27 +346,27 @@ export class ElasticsearchModelService implements
|
|
|
353
346
|
|
|
354
347
|
// Expiry
|
|
355
348
|
deleteExpired<T extends ModelType>(cls: Class<T>): Promise<number> {
|
|
356
|
-
return
|
|
349
|
+
return ModelQueryCrudUtil.deleteExpired(this, cls);
|
|
357
350
|
}
|
|
358
351
|
|
|
359
352
|
// Indexed
|
|
360
353
|
async getByIndex<T extends ModelType>(cls: Class<T>, idx: string, body: DeepPartial<T>): Promise<T> {
|
|
361
354
|
const { key } = ModelIndexedUtil.computeIndexKey(cls, idx, body);
|
|
362
|
-
const
|
|
355
|
+
const result = await this.execSearch<T>(cls, {
|
|
363
356
|
query: ElasticsearchQueryUtil.getSearchQuery(cls,
|
|
364
357
|
ElasticsearchQueryUtil.extractWhereTermQuery(cls,
|
|
365
358
|
ModelIndexedUtil.projectIndex(cls, idx, body))
|
|
366
359
|
)
|
|
367
360
|
});
|
|
368
|
-
if (!
|
|
361
|
+
if (!result.hits.hits.length) {
|
|
369
362
|
throw new NotFoundError(`${cls.name}: ${idx}`, key);
|
|
370
363
|
}
|
|
371
|
-
return this.postLoad(cls,
|
|
364
|
+
return this.postLoad(cls, result.hits.hits[0]);
|
|
372
365
|
}
|
|
373
366
|
|
|
374
367
|
async deleteByIndex<T extends ModelType>(cls: Class<T>, idx: string, body: DeepPartial<T>): Promise<void> {
|
|
375
368
|
const { key } = ModelIndexedUtil.computeIndexKey(cls, idx, body);
|
|
376
|
-
const
|
|
369
|
+
const result = await this.client.deleteByQuery({
|
|
377
370
|
index: this.manager.getIdentity(cls).index,
|
|
378
371
|
query: ElasticsearchQueryUtil.getSearchQuery(cls,
|
|
379
372
|
ElasticsearchQueryUtil.extractWhereTermQuery(cls,
|
|
@@ -381,7 +374,7 @@ export class ElasticsearchModelService implements
|
|
|
381
374
|
),
|
|
382
375
|
refresh: true
|
|
383
376
|
});
|
|
384
|
-
if (
|
|
377
|
+
if (result.deleted) {
|
|
385
378
|
return;
|
|
386
379
|
}
|
|
387
380
|
throw new NotFoundError(`${cls.name}: ${idx}`, key);
|
|
@@ -444,8 +437,8 @@ export class ElasticsearchModelService implements
|
|
|
444
437
|
await QueryVerifier.verify(cls, query);
|
|
445
438
|
|
|
446
439
|
const req = ElasticsearchQueryUtil.getSearchObject(cls, { ...query, limit: 0 }, this.config.schemaConfig);
|
|
447
|
-
const
|
|
448
|
-
return typeof
|
|
440
|
+
const result: number | { value: number } = (await this.execSearch(cls, req)).hits.total || { value: 0 };
|
|
441
|
+
return typeof result !== 'number' ? result.value : result;
|
|
449
442
|
}
|
|
450
443
|
|
|
451
444
|
// Query Crud
|
|
@@ -471,7 +464,7 @@ export class ElasticsearchModelService implements
|
|
|
471
464
|
const copy = BindUtil.bindSchemaToObject(cls, asFull<T>({}), item);
|
|
472
465
|
|
|
473
466
|
try {
|
|
474
|
-
const
|
|
467
|
+
const result = await this.client.updateByQuery({
|
|
475
468
|
...this.manager.getIdentity(cls),
|
|
476
469
|
refresh: true,
|
|
477
470
|
query: search.query,
|
|
@@ -479,7 +472,7 @@ export class ElasticsearchModelService implements
|
|
|
479
472
|
script: ElasticsearchSchemaUtil.generateReplaceScript(castTo(copy))
|
|
480
473
|
});
|
|
481
474
|
|
|
482
|
-
if (
|
|
475
|
+
if (result.version_conflicts || result.updated === undefined || result.updated === 0) {
|
|
483
476
|
throw new NotFoundError(cls, id);
|
|
484
477
|
}
|
|
485
478
|
} catch (err) {
|
|
@@ -497,12 +490,12 @@ export class ElasticsearchModelService implements
|
|
|
497
490
|
await QueryVerifier.verify(cls, query);
|
|
498
491
|
|
|
499
492
|
const { sort: _, ...q } = ElasticsearchQueryUtil.getSearchObject(cls, query, this.config.schemaConfig, false);
|
|
500
|
-
const
|
|
493
|
+
const result = await this.client.deleteByQuery({
|
|
501
494
|
...this.manager.getIdentity(cls),
|
|
502
495
|
...q,
|
|
503
496
|
refresh: true,
|
|
504
497
|
});
|
|
505
|
-
return
|
|
498
|
+
return result.deleted ?? 0;
|
|
506
499
|
}
|
|
507
500
|
|
|
508
501
|
async updatePartialByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>, data: Partial<T>): Promise<number> {
|
|
@@ -512,14 +505,14 @@ export class ElasticsearchModelService implements
|
|
|
512
505
|
const script = ElasticsearchSchemaUtil.generateUpdateScript(item);
|
|
513
506
|
|
|
514
507
|
const search = ElasticsearchQueryUtil.getSearchObject(cls, query, this.config.schemaConfig);
|
|
515
|
-
const
|
|
508
|
+
const result = await this.client.updateByQuery({
|
|
516
509
|
...this.manager.getIdentity(cls),
|
|
517
510
|
refresh: true,
|
|
518
511
|
query: search.query,
|
|
519
512
|
script,
|
|
520
513
|
});
|
|
521
514
|
|
|
522
|
-
return
|
|
515
|
+
return result.updated ?? 0;
|
|
523
516
|
}
|
|
524
517
|
|
|
525
518
|
// Query Facet
|
|
@@ -528,8 +521,8 @@ export class ElasticsearchModelService implements
|
|
|
528
521
|
|
|
529
522
|
const q = ModelQuerySuggestUtil.getSuggestQuery<T>(cls, field, prefix, query);
|
|
530
523
|
const search = ElasticsearchQueryUtil.getSearchObject(cls, q);
|
|
531
|
-
const
|
|
532
|
-
const all = await Promise.all(
|
|
524
|
+
const result = await this.execSearch(cls, search);
|
|
525
|
+
const all = await Promise.all(result.hits.hits.map(x => this.postLoad(cls, x)));
|
|
533
526
|
return ModelQuerySuggestUtil.combineSuggestResults(cls, field, prefix, all, (x, v) => v, query && query.limit);
|
|
534
527
|
}
|
|
535
528
|
|
|
@@ -541,13 +534,13 @@ export class ElasticsearchModelService implements
|
|
|
541
534
|
...query
|
|
542
535
|
});
|
|
543
536
|
const search = ElasticsearchQueryUtil.getSearchObject(cls, q);
|
|
544
|
-
const
|
|
545
|
-
const all = await Promise.all(
|
|
537
|
+
const result = await this.execSearch(cls, search);
|
|
538
|
+
const all = await Promise.all(result.hits.hits.map(x => castTo<T>(({ [field]: field === 'id' ? x._id : x._source![field] }))));
|
|
546
539
|
return ModelQuerySuggestUtil.combineSuggestResults(cls, field, prefix, all, x => x, query && query.limit);
|
|
547
540
|
}
|
|
548
541
|
|
|
549
542
|
// Facet
|
|
550
|
-
async facet<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, query?: ModelQuery<T>): Promise<
|
|
543
|
+
async facet<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, query?: ModelQuery<T>): Promise<ModelQueryFacet[]> {
|
|
551
544
|
await QueryVerifier.verify(cls, query);
|
|
552
545
|
|
|
553
546
|
const q = ElasticsearchQueryUtil.getSearchObject(cls, query ?? {}, this.config.schemaConfig);
|
|
@@ -560,8 +553,8 @@ export class ElasticsearchModelService implements
|
|
|
560
553
|
size: 0
|
|
561
554
|
};
|
|
562
555
|
|
|
563
|
-
const
|
|
564
|
-
const { buckets } = castTo<estypes.AggregationsStringTermsAggregate>('buckets' in
|
|
556
|
+
const result = await this.execSearch(cls, search);
|
|
557
|
+
const { buckets } = castTo<estypes.AggregationsStringTermsAggregate>('buckets' in result.aggregations![field] ? result.aggregations![field] : { buckets: [] });
|
|
565
558
|
const out = Array.isArray(buckets) ? buckets.map(b => ({ key: b.key, count: b.doc_count })) : [];
|
|
566
559
|
return out;
|
|
567
560
|
}
|