From ec1d8b5260ad06adbc6b54d69eda9a2028f22d12 Mon Sep 17 00:00:00 2001 From: Alejandro Marulanda Date: Wed, 17 Apr 2024 12:09:35 +0200 Subject: [PATCH 1/4] Add lang and params to RuntimeField --- package.json | 3 ++- src/core/runtime-field.js | 30 ++++++++++++++++++++-- src/index.d.ts | 27 +++++++++++++++---- test/core-test/request-body-search.test.js | 22 ++++++++++++++++ test/core-test/runtime-field.test.js | 18 +++++++++++++ 5 files changed, 92 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 3df0fdd..1e2ff23 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "kennylindahl ", "foxstarius ", "sandeep952 ", - "florian-lackner365 " + "florian-lackner365 ", + "Alejandro Marulanda " ] } diff --git a/src/core/runtime-field.js b/src/core/runtime-field.js index 5820d0b..0580f12 100644 --- a/src/core/runtime-field.js +++ b/src/core/runtime-field.js @@ -33,6 +33,7 @@ class RuntimeField { this._body = {}; this._isTypeSet = false; this._isScriptSet = false; + this._isParamsSet = false; if (!isNil(type)) { this.type(type); @@ -46,19 +47,20 @@ class RuntimeField { /** * Sets the source of the script. * @param {string} script - * @returns {void} + * @returns {RuntimeField} returns `this` so that calls can be chained. */ script(script) { this._body.script = { source: script }; this._isScriptSet = true; + return this; } /** * Sets the type of the runtime field. * @param {string} type One of `boolean`, `composite`, `date`, `double`, `geo_point`, `ip`, `keyword`, `long`, `lookup`. - * @returns {void} + * @returns {RuntimeField} returns `this` so that calls can be chained. */ type(type) { const typeLower = type.toLowerCase(); @@ -67,6 +69,30 @@ class RuntimeField { } this._body.type = typeLower; this._isTypeSet = true; + return this; + } + + /** + * Specifies the language the script is written in. Defaults to `painless` but + * may be set to any of languages listed in [Scripting](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html). + * + * @param {string} lang The language for the script. + * @returns {RuntimeField} returns `this` so that calls can be chained. + */ + lang(lang) { + this._body.lang = lang; + return this; + } + + /** + * Specifies any named parameters that are passed into the script as variables. + * + * @param {Object} params Named parameters to be passed to script. + * @returns {RuntimeField} returns `this` so that calls can be chained. + */ + params(params) { + this._body.params = params; + return this; } /** diff --git a/src/index.d.ts b/src/index.d.ts index e9d7d48..f808e03 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -8924,17 +8924,34 @@ declare namespace esb { * Sets the type of the runtime field. * * @param {string} type One of `boolean`, `composite`, `date`, `double`, `geo_point`, `ip`, `keyword`, `long`, `lookup`. - * @returns {void} + * @returns {RuntimeField} returns `this` so that calls can be chained. */ - type(type: 'boolean' | 'composite' | 'date' | 'double' | 'geo_point' | 'ip' | 'keyword' | 'long' | 'lookup'): void; + type(type: 'boolean' | 'composite' | 'date' | 'double' | 'geo_point' | 'ip' | 'keyword' | 'long' | 'lookup'): this; /** * Sets the source of the script. * - * @param {string} script - * @returns {void} + * @param {string} script + * @returns {RuntimeField} returns `this` so that calls can be chained. + */ + script(script: string): this; + + /** + * Specifies the language the script is written in. Defaults to `painless` but + * may be set to any of languages listed in [Scripting](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html). + * + * @param {string} lang The language for the script. + * @returns {RuntimeField} returns `this` so that calls can be chained. */ - script(script: string): void; + lang(lang: string): this; + + /** + * Specifies any named parameters that are passed into the script as variables. + * + * @param {object} params Named parameters to be passed to script. + * @returns {RuntimeField} returns `this` so that calls can be chained. + */ + params(params: object): this; /** * Override default `toJSON` to return DSL representation for the `script`. diff --git a/test/core-test/request-body-search.test.js b/test/core-test/request-body-search.test.js index 47b1191..ef1260a 100644 --- a/test/core-test/request-body-search.test.js +++ b/test/core-test/request-body-search.test.js @@ -44,6 +44,12 @@ const runtimeFieldB = new RuntimeField( 'boolean', "emit(doc['qty'].value > 10)" ); +const runtimeFieldC = new RuntimeField( + 'keyword', + "emit(doc['my_field_name'].value * params.factor)" +) + .lang('painless') + .params({ factor: 2.0 }); const scriptA = new Script('inline', "doc['my_field_name'].value * 2").lang( 'painless' @@ -170,6 +176,22 @@ test(setsOption, 'runtimeMappings', { }, keyName: 'runtime_mappings' }); +test('Runtime mappging with lang and params', setsOption, 'runtimeMapping', { + param: ['test1', runtimeFieldC], + propValue: { + test1: { + type: 'keyword', + lang: 'painless', + script: { + source: "emit(doc['my_field_name'].value * params.factor)" + }, + params: { + factor: 2.0 + } + } + }, + keyName: 'runtime_mappings' +}); test(setsOption, 'scriptField', { param: ['test1', scriptA], diff --git a/test/core-test/runtime-field.test.js b/test/core-test/runtime-field.test.js index 4d487bb..2d9a110 100644 --- a/test/core-test/runtime-field.test.js +++ b/test/core-test/runtime-field.test.js @@ -51,3 +51,21 @@ test('script method sets script source', t => { }; t.deepEqual(fieldA.toJSON(), expected); }); + +test('set script, lang and params', t => { + const fieldA = new RuntimeField('keyword'); + fieldA.script("emit(doc['my_field_name'].value * params.factor)"); + fieldA.lang('painless'); + fieldA.params({ factor: 2.0 }); + const expected = { + type: 'keyword', + lang: 'painless', + script: { + source: "emit(doc['my_field_name'].value * params.factor)" + }, + params: { + factor: 2.0 + } + }; + t.deepEqual(fieldA.toJSON(), expected); +}); From 219e9498b972745824ae186327094265b26429d3 Mon Sep 17 00:00:00 2001 From: Alejandro Marulanda Date: Thu, 18 Apr 2024 10:19:26 +0200 Subject: [PATCH 2/4] Move RuntimeField lang and params inside script --- src/core/runtime-field.js | 8 ++++++-- test/core-test/request-body-search.test.js | 10 +++++----- test/core-test/runtime-field.test.js | 10 +++++----- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/core/runtime-field.js b/src/core/runtime-field.js index 0580f12..c939abd 100644 --- a/src/core/runtime-field.js +++ b/src/core/runtime-field.js @@ -80,7 +80,9 @@ class RuntimeField { * @returns {RuntimeField} returns `this` so that calls can be chained. */ lang(lang) { - this._body.lang = lang; + if (!isNil(this._body.script)) { + this._body.script.lang = lang; + } return this; } @@ -91,7 +93,9 @@ class RuntimeField { * @returns {RuntimeField} returns `this` so that calls can be chained. */ params(params) { - this._body.params = params; + if (!isNil(this._body.script)) { + this._body.script.params = params; + } return this; } diff --git a/test/core-test/request-body-search.test.js b/test/core-test/request-body-search.test.js index ef1260a..9fbf645 100644 --- a/test/core-test/request-body-search.test.js +++ b/test/core-test/request-body-search.test.js @@ -181,12 +181,12 @@ test('Runtime mappging with lang and params', setsOption, 'runtimeMapping', { propValue: { test1: { type: 'keyword', - lang: 'painless', script: { - source: "emit(doc['my_field_name'].value * params.factor)" - }, - params: { - factor: 2.0 + lang: 'painless', + source: "emit(doc['my_field_name'].value * params.factor)", + params: { + factor: 2.0 + } } } }, diff --git a/test/core-test/runtime-field.test.js b/test/core-test/runtime-field.test.js index 2d9a110..d4f461f 100644 --- a/test/core-test/runtime-field.test.js +++ b/test/core-test/runtime-field.test.js @@ -59,12 +59,12 @@ test('set script, lang and params', t => { fieldA.params({ factor: 2.0 }); const expected = { type: 'keyword', - lang: 'painless', script: { - source: "emit(doc['my_field_name'].value * params.factor)" - }, - params: { - factor: 2.0 + lang: 'painless', + source: "emit(doc['my_field_name'].value * params.factor)", + params: { + factor: 2.0 + } } }; t.deepEqual(fieldA.toJSON(), expected); From 1bc713da4a0fe0dfa8dab14a7f00ca861bcf8887 Mon Sep 17 00:00:00 2001 From: Alejandro Marulanda Date: Thu, 18 Apr 2024 17:12:27 +0200 Subject: [PATCH 3/4] Remove unneeded _isParamsSet field --- src/core/runtime-field.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/runtime-field.js b/src/core/runtime-field.js index c939abd..570fc41 100644 --- a/src/core/runtime-field.js +++ b/src/core/runtime-field.js @@ -33,7 +33,6 @@ class RuntimeField { this._body = {}; this._isTypeSet = false; this._isScriptSet = false; - this._isParamsSet = false; if (!isNil(type)) { this.type(type); From cf92eda37f99103d3dff206e5817745ebb9d513c Mon Sep 17 00:00:00 2001 From: Alejandro Marulanda Date: Mon, 6 May 2024 16:32:17 +0200 Subject: [PATCH 4/4] Increase request-body-search coverage to 100 --- test/core-test/runtime-field.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/core-test/runtime-field.test.js b/test/core-test/runtime-field.test.js index d4f461f..610c539 100644 --- a/test/core-test/runtime-field.test.js +++ b/test/core-test/runtime-field.test.js @@ -69,3 +69,11 @@ test('set script, lang and params', t => { }; t.deepEqual(fieldA.toJSON(), expected); }); + +test("don't set lang and params if script is not set", t => { + const fieldA = new RuntimeField('keyword'); + fieldA.lang('painless'); + fieldA.params({ factor: 2.0 }); + const error = t.throws(() => fieldA.toJSON()); + t.is(error.message, '`script` should be set'); +});