From 847525fcb2a75899e426a938c922133ec23a9f6d Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Wed, 25 Oct 2023 13:49:02 +0200 Subject: [PATCH 01/10] fix: improved elastic search query filter --- .../interfaces/es-common.type.ts | 7 +++++++ .../providers/query-builder.service.ts | 19 +++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/elastic-search/interfaces/es-common.type.ts b/src/elastic-search/interfaces/es-common.type.ts index ad4888a2e..6cd6e73d3 100644 --- a/src/elastic-search/interfaces/es-common.type.ts +++ b/src/elastic-search/interfaces/es-common.type.ts @@ -22,6 +22,13 @@ export interface IShould { }; } +export interface IBoolShould { + bool: { + should: IShould[]; + minimum_should_match?: number; + }; +} + export interface IFilter { terms?: { [key: string]: string[]; diff --git a/src/elastic-search/providers/query-builder.service.ts b/src/elastic-search/providers/query-builder.service.ts index 2530e1282..6dba04840 100644 --- a/src/elastic-search/providers/query-builder.service.ts +++ b/src/elastic-search/providers/query-builder.service.ts @@ -1,7 +1,12 @@ import { Injectable, Logger } from "@nestjs/common"; import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types"; import { IDatasetFields } from "src/datasets/interfaces/dataset-filters.interface"; -import { IFilter, IShould, ObjectType } from "../interfaces/es-common.type"; +import { + IBoolShould, + IFilter, + IShould, + ObjectType, +} from "../interfaces/es-common.type"; import { FilterFields, QueryFields } from "./fields.enum"; import { mapScientificQuery } from "src/common/utils"; import { IScientificFilter } from "src/common/interfaces/common.interface"; @@ -57,7 +62,7 @@ export class SearchQueryService { shouldFilter.push(ownerGroup, accessGroups); } - return shouldFilter; + return { bool: { should: shouldFilter, minimum_should_match: 1 } }; } private buildTextQuery(text: string): QueryDslQueryContainer[] { @@ -161,19 +166,13 @@ export class SearchQueryService { private constructFinalQuery( filter: IFilter[], - should: IShould[], + should: IBoolShould, query: QueryDslQueryContainer[], ) { const finalQuery = { query: { bool: { - filter, - should: { - bool: { - should, - minimum_should_match: 1, - }, - }, + filter: [...filter, should], must: query, }, }, From 13c282f7ba2a530c82f9071a89b7ca512db7cf63 Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Wed, 25 Oct 2023 08:55:54 +0200 Subject: [PATCH 02/10] fix: updated mathJS package version && improved number check --- package-lock.json | 2 +- package.json | 5 ++--- src/elastic-search/helpers/utils.ts | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cf24f3c9..8b05a13d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "handlebars": "^4.7.7", "lodash": "^4.17.21", "luxon": "^3.2.1", - "mathjs": "^11.4.0", + "mathjs": "^11.11.2", "migrate-mongo": "^11.0.0", "mongoose": "^7.4.3", "node-fetch": "^3.3.0", diff --git a/package.json b/package.json index d0b14b485..be63857e7 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "handlebars": "^4.7.7", "lodash": "^4.17.21", "luxon": "^3.2.1", - "mathjs": "^11.4.0", + "mathjs": "^11.11.2", "migrate-mongo": "^11.0.0", "mongoose": "^7.4.3", "node-fetch": "^3.3.0", @@ -124,8 +124,7 @@ "transform": { "^.+\\.(t|j)s$": "ts-jest" }, - "transformIgnorePatterns": [ - ], + "transformIgnorePatterns": [], "collectCoverageFrom": [ "**/*.(t|j)s" ], diff --git a/src/elastic-search/helpers/utils.ts b/src/elastic-search/helpers/utils.ts index 9e64899e3..3c8c7ba2a 100644 --- a/src/elastic-search/helpers/utils.ts +++ b/src/elastic-search/helpers/utils.ts @@ -10,9 +10,8 @@ export const transformKeysInObject = (obj: Record) => { for (const [key, value] of Object.entries(obj)) { const newKey = transformKey(key); - const isNumberValueType = Number.isInteger( - (value as Record)?.value, - ); + const isNumberValueType = + typeof (value as Record)?.value === "number"; if (isNumberValueType) { (value as Record)["value_type"] = "number"; } else { From 1855882ba805cef49f0be904093be0e018cc981e Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Thu, 26 Oct 2023 16:49:50 +0200 Subject: [PATCH 03/10] fix: fixed inconsistency between data list and count number --- src/common/utils.ts | 13 ++++++++----- src/datasets/datasets.service.ts | 12 ++++++------ src/elastic-search/configuration/indexSetting.ts | 11 ++++++++++- src/elastic-search/helpers/utils.ts | 4 ++-- src/elastic-search/interfaces/es-common.type.ts | 3 +++ 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/common/utils.ts b/src/common/utils.ts index 777c2b5ff..1cd693f2c 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -612,6 +612,7 @@ export const createFullfacetPipeline = ( fields: Y, facets: string[], subField = "", + esEnabled = false, ): PipelineStage[] => { const pipeline: PipelineStage[] = []; const facetMatch: Record = {}; @@ -621,6 +622,13 @@ export const createFullfacetPipeline = ( facetMatch[key] = searchExpression(model, key, fields[key as keyof Y]); } + if (esEnabled) { + if (key === "mode") { + pipelineHandler.handleModeSearch(pipeline, fields, key, idField); + } + return; + } + switch (key) { case "text": pipelineHandler.handleTextSearch(pipeline, model, fields, key); @@ -906,11 +914,6 @@ const replaceLikeOperatorRecursive = ( return output; }; -export const isObjectWithOneKey = (obj: object): boolean => { - const keys = Object.keys(obj); - return keys.length === 1; -}; - export const sleep = (ms: number) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; diff --git a/src/datasets/datasets.service.ts b/src/datasets/datasets.service.ts index 2032a5d32..802cebd33 100644 --- a/src/datasets/datasets.service.ts +++ b/src/datasets/datasets.service.ts @@ -18,7 +18,6 @@ import { createFullfacetPipeline, createFullqueryFilter, extractMetadataKeys, - isObjectWithOneKey, parseLimitFilters, } from "src/common/utils"; import { ElasticSearchService } from "src/elastic-search/elastic-search.service"; @@ -109,7 +108,9 @@ export class DatasetsService { }; const modifiers: QueryOptions = parseLimitFilters(filter.limits); - if (!this.ESClient || !whereClause) { + const noFilter = Object.keys(whereClause).length === 0; + + if (!this.ESClient || noFilter) { datasets = await this.datasetModel .find(whereClause, null, modifiers) .exec(); @@ -133,13 +134,11 @@ export class DatasetsService { ): Promise[]> { const fields = filters.fields ?? {}; const facets = filters.facets ?? []; - // NOTE: if fields contains no value, we should use mongo query to optimize performance. // however, fields always contain mode key, so we need to check if there's more than one key - const isFieldsEmpty = isObjectWithOneKey(fields); - + const isFieldsEmpty = Object.keys(fields).length === 1; let data; - if (this.ESClient && !isFieldsEmpty) { + if (!!this.ESClient && !isFieldsEmpty) { const totalDocCount = await this.datasetModel.countDocuments(); const { data: esPids } = await this.ESClient.search( @@ -154,6 +153,7 @@ export class DatasetsService { fields, facets, "", + !!this.ESClient, ); data = await this.datasetModel.aggregate(pipeline).exec(); diff --git a/src/elastic-search/configuration/indexSetting.ts b/src/elastic-search/configuration/indexSetting.ts index 6ab3584aa..fc9aa5e59 100644 --- a/src/elastic-search/configuration/indexSetting.ts +++ b/src/elastic-search/configuration/indexSetting.ts @@ -44,7 +44,16 @@ export const dynamic_template: }, }, }, - + { + double_as_double: { + path_match: "scientificMetadata.*.*", + match_mapping_type: "double", + mapping: { + type: "double", + ignore_malformed: true, + }, + }, + }, { date_as_keyword: { path_match: "scientificMetadata.*.*", diff --git a/src/elastic-search/helpers/utils.ts b/src/elastic-search/helpers/utils.ts index 3c8c7ba2a..0f93f28da 100644 --- a/src/elastic-search/helpers/utils.ts +++ b/src/elastic-search/helpers/utils.ts @@ -83,7 +83,7 @@ export const convertToElasticSearchQuery = ( if (fieldType === "valueSI" || fieldType === "value") { const numberFilter = { - term: { + match: { [`${firstPart}.${middlePart}.value_type`]: typeof value === "number" ? "number" : "string", }, @@ -94,7 +94,7 @@ export const convertToElasticSearchQuery = ( filter = esOperation === "eq" ? { - term: { [`${transformedKey}`]: value }, + match: { [`${transformedKey}`]: value }, } : { range: { [`${transformedKey}`]: { [esOperation]: value } } }; diff --git a/src/elastic-search/interfaces/es-common.type.ts b/src/elastic-search/interfaces/es-common.type.ts index 6cd6e73d3..01a07e129 100644 --- a/src/elastic-search/interfaces/es-common.type.ts +++ b/src/elastic-search/interfaces/es-common.type.ts @@ -42,6 +42,9 @@ export interface IFilter { lte?: string | number; }; }; + match?: { + [key: string]: string | number; + }; nested?: { path: string; query: { From e48771f0c592e00334bd475a3cc2723237f8867f Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Fri, 27 Oct 2023 09:18:19 +0200 Subject: [PATCH 04/10] fix: minor naming change --- src/datasets/datasets.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/datasets/datasets.service.ts b/src/datasets/datasets.service.ts index 802cebd33..c7f9ac325 100644 --- a/src/datasets/datasets.service.ts +++ b/src/datasets/datasets.service.ts @@ -108,9 +108,9 @@ export class DatasetsService { }; const modifiers: QueryOptions = parseLimitFilters(filter.limits); - const noFilter = Object.keys(whereClause).length === 0; + const isFieldsEmpty = Object.keys(whereClause).length === 0; - if (!this.ESClient || noFilter) { + if (!this.ESClient || isFieldsEmpty) { datasets = await this.datasetModel .find(whereClause, null, modifiers) .exec(); From e0915e187b061101057033fdb397ccc365cac35d Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Fri, 27 Oct 2023 11:46:42 +0200 Subject: [PATCH 05/10] fix: improved mapping for digit with floating points --- src/elastic-search/configuration/indexSetting.ts | 11 +---------- src/elastic-search/helpers/utils.ts | 4 ++-- src/elastic-search/interfaces/es-common.type.ts | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/elastic-search/configuration/indexSetting.ts b/src/elastic-search/configuration/indexSetting.ts index fc9aa5e59..6a558a607 100644 --- a/src/elastic-search/configuration/indexSetting.ts +++ b/src/elastic-search/configuration/indexSetting.ts @@ -38,18 +38,9 @@ export const dynamic_template: long_as_long: { path_match: "scientificMetadata.*.*", match_mapping_type: "long", - mapping: { - type: "long", - ignore_malformed: true, - }, - }, - }, - { - double_as_double: { - path_match: "scientificMetadata.*.*", - match_mapping_type: "double", mapping: { type: "double", + coerce: true, ignore_malformed: true, }, }, diff --git a/src/elastic-search/helpers/utils.ts b/src/elastic-search/helpers/utils.ts index 0f93f28da..3c8c7ba2a 100644 --- a/src/elastic-search/helpers/utils.ts +++ b/src/elastic-search/helpers/utils.ts @@ -83,7 +83,7 @@ export const convertToElasticSearchQuery = ( if (fieldType === "valueSI" || fieldType === "value") { const numberFilter = { - match: { + term: { [`${firstPart}.${middlePart}.value_type`]: typeof value === "number" ? "number" : "string", }, @@ -94,7 +94,7 @@ export const convertToElasticSearchQuery = ( filter = esOperation === "eq" ? { - match: { [`${transformedKey}`]: value }, + term: { [`${transformedKey}`]: value }, } : { range: { [`${transformedKey}`]: { [esOperation]: value } } }; diff --git a/src/elastic-search/interfaces/es-common.type.ts b/src/elastic-search/interfaces/es-common.type.ts index 01a07e129..916107054 100644 --- a/src/elastic-search/interfaces/es-common.type.ts +++ b/src/elastic-search/interfaces/es-common.type.ts @@ -50,7 +50,7 @@ export interface IFilter { query: { bool: { must: ( - | { match?: { [key: string]: string } } + | { term?: { [key: string]: string } } | { range?: { [key: string]: { [key: string]: string | number } } } )[]; }; From 371e98e9d24ded39b588e3774527f750181686dd Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Mon, 30 Oct 2023 12:52:11 +0100 Subject: [PATCH 06/10] fix: revert back to mongo query if es db doesnt return any value --- src/datasets/datasets.service.ts | 37 +++++++++++++------- src/elastic-search/elastic-search.service.ts | 12 +++++++ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/datasets/datasets.service.ts b/src/datasets/datasets.service.ts index c7f9ac325..d77510010 100644 --- a/src/datasets/datasets.service.ts +++ b/src/datasets/datasets.service.ts @@ -110,7 +110,10 @@ export class DatasetsService { const isFieldsEmpty = Object.keys(whereClause).length === 0; - if (!this.ESClient || isFieldsEmpty) { + // NOTE: if Elastic search DB is empty we should use default mongo query + const canPerformElasticSearchQueries = await this.isElasticSearchDBEmpty(); + + if (!this.ESClient || isFieldsEmpty || !canPerformElasticSearchQueries) { datasets = await this.datasetModel .find(whereClause, null, modifiers) .exec(); @@ -135,38 +138,40 @@ export class DatasetsService { const fields = filters.fields ?? {}; const facets = filters.facets ?? []; // NOTE: if fields contains no value, we should use mongo query to optimize performance. - // however, fields always contain mode key, so we need to check if there's more than one key + // however, fields always contain "mode" key, so we need to check if there's more than one key const isFieldsEmpty = Object.keys(fields).length === 1; - let data; - if (!!this.ESClient && !isFieldsEmpty) { - const totalDocCount = await this.datasetModel.countDocuments(); - const { data: esPids } = await this.ESClient.search( - fields as IDatasetFields, - totalDocCount, - ); - - fields.mode = { _id: { $in: esPids } }; + // NOTE: if Elastic search DB is empty we should use default mongo query + const canPerformElasticSearchQueries = await this.isElasticSearchDBEmpty(); + let data; + if (!this.ESClient || isFieldsEmpty || !canPerformElasticSearchQueries) { const pipeline = createFullfacetPipeline( this.datasetModel, "pid", fields, facets, "", - !!this.ESClient, ); data = await this.datasetModel.aggregate(pipeline).exec(); } else { + const { totalCount, data: esPids } = await this.ESClient.search( + fields as IDatasetFields, + 0, + ); + + fields.mode = { _id: { $in: esPids } }; const pipeline = createFullfacetPipeline( this.datasetModel, "pid", fields, facets, "", + !!this.ESClient, ); - data = await this.datasetModel.aggregate(pipeline).exec(); + // NOTE: below code is to overwrite totalCount with ES result + data[0].all = [{ totalSets: totalCount }]; } return data; @@ -488,4 +493,10 @@ export class DatasetsService { } } } + + async isElasticSearchDBEmpty() { + if (!this.ESClient) return; + const count = await this.ESClient.getCount(); + return count.count > 0; + } } diff --git a/src/elastic-search/elastic-search.service.ts b/src/elastic-search/elastic-search.service.ts index f17dc48d5..29b8e816a 100644 --- a/src/elastic-search/elastic-search.service.ts +++ b/src/elastic-search/elastic-search.service.ts @@ -176,6 +176,18 @@ export class ElasticSearchService implements OnModuleInit { return bulkResponse; } + async getCount(index = this.defaultIndex) { + try { + return await this.esService.count({ index }); + } catch (error) { + Logger.error("getCount failed-> ElasticSearchService", error); + throw new HttpException( + `getCount failed-> ElasticSearchService ${error}`, + HttpStatus.BAD_REQUEST, + ); + } + } + async updateIndex(index = this.defaultIndex) { try { await this.esService.indices.close({ From ffe0da0a773ec3fd06d1e9d46c6de389d6b17d93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 10:09:52 +0000 Subject: [PATCH 07/10] build(deps): bump actions/setup-node from 3 to 4 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 182720c49..086a15f69 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} @@ -42,7 +42,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Cache node_modules @@ -64,7 +64,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} @@ -87,7 +87,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} @@ -116,7 +116,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} @@ -179,7 +179,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} From 102c94277f31eb7439d70770ecdea13e5a7597b8 Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Tue, 31 Oct 2023 11:46:04 +0100 Subject: [PATCH 08/10] fix: fixed pagination conflict between ES and mongo query --- src/datasets/datasets.service.ts | 12 ++++++++---- src/elastic-search/elastic-search.service.ts | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/datasets/datasets.service.ts b/src/datasets/datasets.service.ts index d77510010..b3fe32748 100644 --- a/src/datasets/datasets.service.ts +++ b/src/datasets/datasets.service.ts @@ -123,9 +123,8 @@ export class DatasetsService { modifiers.limit, modifiers.skip, ); - datasets = await this.datasetModel - .find({ _id: { $in: esResult.data } }, null, modifiers) + .find({ _id: { $in: esResult.data } }) .exec(); } @@ -135,15 +134,18 @@ export class DatasetsService { async fullFacet( filters: IFacets, ): Promise[]> { + let data; + const fields = filters.fields ?? {}; const facets = filters.facets ?? []; + // NOTE: if fields contains no value, we should use mongo query to optimize performance. // however, fields always contain "mode" key, so we need to check if there's more than one key const isFieldsEmpty = Object.keys(fields).length === 1; // NOTE: if Elastic search DB is empty we should use default mongo query const canPerformElasticSearchQueries = await this.isElasticSearchDBEmpty(); - let data; + if (!this.ESClient || isFieldsEmpty || !canPerformElasticSearchQueries) { const pipeline = createFullfacetPipeline( this.datasetModel, @@ -155,9 +157,10 @@ export class DatasetsService { data = await this.datasetModel.aggregate(pipeline).exec(); } else { + const { count: initialCount } = await this.ESClient.getCount(); const { totalCount, data: esPids } = await this.ESClient.search( fields as IDatasetFields, - 0, + initialCount, ); fields.mode = { _id: { $in: esPids } }; @@ -170,6 +173,7 @@ export class DatasetsService { !!this.ESClient, ); data = await this.datasetModel.aggregate(pipeline).exec(); + // NOTE: below code is to overwrite totalCount with ES result data[0].all = [{ totalSets: totalCount }]; } diff --git a/src/elastic-search/elastic-search.service.ts b/src/elastic-search/elastic-search.service.ts index 29b8e816a..982faa9e9 100644 --- a/src/elastic-search/elastic-search.service.ts +++ b/src/elastic-search/elastic-search.service.ts @@ -259,7 +259,8 @@ export class ElasticSearchService implements OnModuleInit { const searchOptions = { track_scores: true, body: searchQuery, - size: limit + skip, + from: skip, + size: limit, sort: [{ _score: { order: "desc" } }], min_score: defaultMinScore, track_total_hits: true, From 3f3e48853da7178f01c85751b74812d637415944 Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Tue, 31 Oct 2023 11:47:27 +0100 Subject: [PATCH 09/10] fix: remove empty space in string value of condition filter with trim() --- src/elastic-search/helpers/utils.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/elastic-search/helpers/utils.ts b/src/elastic-search/helpers/utils.ts index 3c8c7ba2a..a34fbb78b 100644 --- a/src/elastic-search/helpers/utils.ts +++ b/src/elastic-search/helpers/utils.ts @@ -70,11 +70,17 @@ export const convertToElasticSearchQuery = ( for (const field in scientificQuery) { const query = scientificQuery[field] as Record; const operation = Object.keys(query)[0]; - const value = query[operation]; + const value = + typeof query[operation] === "string" + ? (query[operation] as string).trim() + : query[operation]; + const esOperation = operation.replace("$", ""); - // Example: trasnformedKey = "scientificMetadata.someKey.value" - // firstPart = "scientificMetadata" , middlePart = "someKey" + // NOTE-EXAMPLE: + // trasnformedKey = "scientificMetadata.someKey.value" + // firstPart = "scientificMetadata", + // middlePart = "someKey" const { transformedKey, firstPart, middlePart } = transformMiddleKey(field); let filter = {}; From 1e6dfc2ed22d90a0e7cb0a91b56da8f118dc288f Mon Sep 17 00:00:00 2001 From: Jay Quan Date: Tue, 31 Oct 2023 13:43:54 +0100 Subject: [PATCH 10/10] fix: minor change for object name and removed redundant type --- src/elastic-search/configuration/indexSetting.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/elastic-search/configuration/indexSetting.ts b/src/elastic-search/configuration/indexSetting.ts index 6a558a607..bbb60a9f2 100644 --- a/src/elastic-search/configuration/indexSetting.ts +++ b/src/elastic-search/configuration/indexSetting.ts @@ -21,9 +21,7 @@ export const special_character_filter: AnalysisPatternReplaceCharFilter = { }; //Dynamic templates -export const dynamic_template: - | Record[] - | never = [ +export const dynamic_template: Record[] = [ { string_as_keyword: { path_match: "scientificMetadata.*.*", @@ -35,7 +33,7 @@ export const dynamic_template: }, }, { - long_as_long: { + long_as_double: { path_match: "scientificMetadata.*.*", match_mapping_type: "long", mapping: {