From 09f73ccccd9bed57b6f430a7cdc2be7ce6e5fd70 Mon Sep 17 00:00:00 2001 From: Trevor Robinson Date: Mon, 1 Jan 2024 07:42:39 -0600 Subject: [PATCH] feat: Add support for script score query (#191) Script score query was added in Elasticsearch v7.0 --- src/index.d.ts | 35 ++++++++++ src/index.js | 4 ++ src/queries/specialized-queries/index.js | 1 + .../specialized-queries/script-score-query.js | 67 +++++++++++++++++++ test/index.test.js | 3 + test/queries-test/script-score-query.test.js | 37 ++++++++++ 6 files changed, 147 insertions(+) create mode 100644 src/queries/specialized-queries/script-score-query.js create mode 100644 test/queries-test/script-score-query.test.js diff --git a/src/index.d.ts b/src/index.d.ts index a5fe430..9a01a76 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -3057,6 +3057,41 @@ declare namespace esb { */ export function scriptQuery(script?: Script): ScriptQuery; + /** + * A query that uses a script to provide a custom score for returned documents. + * + * @extends Query + */ + export class ScriptScoreQuery extends Query { + constructor(); + + /** + * Sets the query used to return documents. + * + * @param {Query} query A valid `Query` object + */ + query(query: Query): this; + + /** + * Sets the script used to compute the score of documents returned by the query. + * + * @param {Script} script A valid `Script` object + */ + script(script: Script): this; + + /** + * Sets the minimum score limit for documents to be included in search result. + * + * @param {number} limit Minimum score threshold + */ + minScore(limit: number): this; + } + + /** + * A query that uses a script to provide a custom score for returned documents. + */ + export function scriptScoreQuery(): ScriptScoreQuery; + /** * The `percolate` query can be used to match queries stored in an index. * The `percolate` query itself contains the document that will be used diff --git a/src/index.js b/src/index.js index ea465fd..af7f821 100644 --- a/src/index.js +++ b/src/index.js @@ -71,6 +71,7 @@ const { specializedQueries: { MoreLikeThisQuery, ScriptQuery, + ScriptScoreQuery, PercolateQuery, DistanceFeatureQuery }, @@ -294,6 +295,9 @@ exports.moreLikeThisQuery = constructorWrapper(MoreLikeThisQuery); exports.ScriptQuery = ScriptQuery; exports.scriptQuery = constructorWrapper(ScriptQuery); +exports.ScriptScoreQuery = ScriptScoreQuery; +exports.scriptScoreQuery = constructorWrapper(ScriptScoreQuery); + exports.PercolateQuery = PercolateQuery; exports.percolateQuery = constructorWrapper(PercolateQuery); diff --git a/src/queries/specialized-queries/index.js b/src/queries/specialized-queries/index.js index c82b060..a760b86 100644 --- a/src/queries/specialized-queries/index.js +++ b/src/queries/specialized-queries/index.js @@ -2,5 +2,6 @@ exports.MoreLikeThisQuery = require('./more-like-this-query'); exports.ScriptQuery = require('./script-query'); +exports.ScriptScoreQuery = require('./script-score-query'); exports.PercolateQuery = require('./percolate-query'); exports.DistanceFeatureQuery = require('./distance-feature-query'); diff --git a/src/queries/specialized-queries/script-score-query.js b/src/queries/specialized-queries/script-score-query.js new file mode 100644 index 0000000..39f6cb1 --- /dev/null +++ b/src/queries/specialized-queries/script-score-query.js @@ -0,0 +1,67 @@ +'use strict'; + +const { + Query, + Script, + util: { checkType } +} = require('../../core'); + +/** + * A query that uses a script to provide a custom score for returned documents. + * + * [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-score-query.html) + * + * NOTE: This query was added in elasticsearch v7.0. + * + * @example + * const qry = esb.scriptScoreQuery() + * .query(esb.matchQuery("message", "elasticsearch")) + * .script(esb.script().source("doc['my-int'].value / 10")) + * + * @extends Query + */ +class ScriptScoreQuery extends Query { + // eslint-disable-next-line require-jsdoc + constructor() { + super('script_score'); + } + + /** + * Sets the query used to return documents. + * + * @param {Query} query A valid `Query` object + * @returns {ScriptScoreQuery} returns `this` so that calls can be chained. + */ + query(query) { + checkType(query, Query); + + this._queryOpts.query = query; + return this; + } + + /** + * Sets the script used to compute the score of documents returned by the query. + * + * @param {Script} script A valid `Script` object + * @returns {ScriptScoreQuery} returns `this` so that calls can be chained. + */ + script(script) { + checkType(script, Script); + + this._queryOpts.script = script; + return this; + } + + /** + * Sets the minimum score limit for documents to be included in search result. + * + * @param {number} limit Minimum score threshold + * @returns {ScriptScoreQuery} returns `this` so that calls can be chained. + */ + minScore(limit) { + this._queryOpts.min_score = limit; + return this; + } +} + +module.exports = ScriptScoreQuery; diff --git a/test/index.test.js b/test/index.test.js index 87514b2..b819256 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -134,6 +134,9 @@ test('queries are exported', t => { t.truthy(esb.ScriptQuery); t.truthy(esb.scriptQuery); + t.truthy(esb.ScriptScoreQuery); + t.truthy(esb.scriptScoreQuery); + t.truthy(esb.PercolateQuery); t.truthy(esb.percolateQuery); diff --git a/test/queries-test/script-score-query.test.js b/test/queries-test/script-score-query.test.js new file mode 100644 index 0000000..2fa4d55 --- /dev/null +++ b/test/queries-test/script-score-query.test.js @@ -0,0 +1,37 @@ +import test from 'ava'; +import { + MatchQuery, + Script, + ScriptScoreQuery, + scriptScoreQuery +} from '../../src'; +import { + illegalParamType, + makeSetsOptionMacro, + nameExpectStrategy +} from '../_macros'; + +const setsOption = makeSetsOptionMacro( + scriptScoreQuery, + nameExpectStrategy('script_score') +); + +const query = new MatchQuery('message', 'elasticsearch'); + +const lang = 'painless'; +const source = + "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)"; +const params = { origin: 20, scale: 10, decay: 0.5, offset: 0 }; +const script = new Script() + .lang(lang) + .source(source) + .params(params); + +const instance = new ScriptScoreQuery(); + +test(illegalParamType, instance, 'query', 'Query'); +test(illegalParamType, instance, 'script', 'Script'); + +test(setsOption, 'query', { param: query }); +test(setsOption, 'script', { param: script }); +test(setsOption, 'minScore', { param: 9.999 });