Skip to content

Commit

Permalink
feat: Add support for script score query (#191)
Browse files Browse the repository at this point in the history
Script score query was added in Elasticsearch v7.0
  • Loading branch information
trevorr authored Jan 1, 2024
1 parent ce60314 commit 09f73cc
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const {
specializedQueries: {
MoreLikeThisQuery,
ScriptQuery,
ScriptScoreQuery,
PercolateQuery,
DistanceFeatureQuery
},
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions src/queries/specialized-queries/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
67 changes: 67 additions & 0 deletions src/queries/specialized-queries/script-score-query.js
Original file line number Diff line number Diff line change
@@ -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;
3 changes: 3 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
37 changes: 37 additions & 0 deletions test/queries-test/script-score-query.test.js
Original file line number Diff line number Diff line change
@@ -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 });

0 comments on commit 09f73cc

Please sign in to comment.