Skip to content

Commit

Permalink
feat: Add rank_feature query (#194)
Browse files Browse the repository at this point in the history
Rank feature query was added in Elasticsearch v7.0.
  • Loading branch information
spinscale authored Feb 25, 2024
1 parent 09f73cc commit 8002c89
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 1 deletion.
80 changes: 80 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3268,6 +3268,86 @@ declare namespace esb {
*/
export function distanceFeatureQuery(field?: string): DistanceFeatureQuery;

/**
* The `rank_feature` query boosts the relevance score on the numeric value of
* document with a rank_feature/rank_features field.
*
* [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-rank-feature-query.html)
*
* NOTE: This query was added in elasticsearch v7.0.
*
* @example
* const query = new RankFeatureQuery('rank_feature_field');
* query
* .linear()
* .toJSON();
* @param {string} field The field inside the document to be used in the query
* @return {RankFeatureQuery}
*/
export class RankFeatureQuery extends Query {
constructor(field?: string);

/**
* Sets the field for the `distance_feature` query
* @param {string} fieldName Name of the field inside the document
* @returns {DistanceFeatureQuery} Instance of the query
*/
field(fieldName: string): RankFeatureQuery;

/**
* Linear function to boost relevance scores based on the value of the rank feature field
* @returns {RankFeatureQuery}
*/
linear() : RankFeatureQuery;

/**
* Saturation function to boost relevance scores based on the value of the rank feature field.
* Uses a default pivot value computed by Elasticsearch.
* @returns {RankFeatureQuery}
*/
saturation() : RankFeatureQuery;

/**
* Saturation function to boost relevance scores based on the value of the rank feature field.
* @param {number} pivot
* @returns {RankFeatureQuery}
*/
saturationPivot(pivot : number) : RankFeatureQuery;

/**
* The log function gives a score equal to log(scaling_factor + S), where S
* is the value of the rank feature field and scaling_factor is a configurable
* scaling factor.
* @param {number} scaling_factor
* @returns {RankFeatureQuery}
*/
log(scalingFactor : number) : RankFeatureQuery;

/**
* The sigmoid function extends the saturation function with a configurable exponent.
* @param {number} pivot
* @param {number} exponent
* @returns {RankFeatureQuery}
*/
sigmoid(pivot : number, exponent : number) : RankFeatureQuery
}

/**
* The `rank_feature` query boosts the relevance score on the numeric value of
* document with a rank_feature/rank_features field.
*
* [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-rank-feature-query.html)
*
* @example
* const query = new RankFeatureQuery('rank_feature_field');
* query
* .linear()
* .toJSON();
* @param {string} field The field inside the document to be used in the query
* @return {RankFeatureQuery}
*/
export function rankFeatureQuery(field?: string): RankFeatureQuery;

/**
* Interface-like class used to group and identify various implementations of Span queries.
*
Expand Down
6 changes: 5 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ const {
ScriptQuery,
ScriptScoreQuery,
PercolateQuery,
DistanceFeatureQuery
DistanceFeatureQuery,
RankFeatureQuery
},
spanQueries: {
SpanTermQuery,
Expand Down Expand Up @@ -304,6 +305,9 @@ exports.percolateQuery = constructorWrapper(PercolateQuery);
exports.DistanceFeatureQuery = DistanceFeatureQuery;
exports.distanceFeatureQuery = constructorWrapper(DistanceFeatureQuery);

exports.RankFeatureQuery = RankFeatureQuery;
exports.rankFeatureQuery = constructorWrapper(RankFeatureQuery);

/* ============ ============ ============ */
/* ============ Span Queries ============ */
/* ============ ============ ============ */
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 @@ -5,3 +5,4 @@ exports.ScriptQuery = require('./script-query');
exports.ScriptScoreQuery = require('./script-score-query');
exports.PercolateQuery = require('./percolate-query');
exports.DistanceFeatureQuery = require('./distance-feature-query');
exports.RankFeatureQuery = require('./rank-feature-query');
98 changes: 98 additions & 0 deletions src/queries/specialized-queries/rank-feature-query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use strict';

const { Query } = require('../../core');
const isNil = require('lodash.isnil');

/**
* The rank_feature query boosts the relevance score on the numeric value of
* document with a rank_feature/rank_features field.
*
* [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-rank-feature-query.html)
*
* NOTE: This query was added in elasticsearch v7.0.
*
* @example
* const query = new RankFeatureQuery('rank_feature_field');
* query
* .linear()
* .toJSON();
* @param {string} field The field inside the document to be used in the query
* @extends Query
*/
class RankFeatureQuery extends Query {
/**
* @param {string} field The field inside the document to be used in the query
*/
constructor(field) {
super('rank_feature');
if (!isNil(field)) this._queryOpts.field = field;
}

/**
* Sets the field for the `rank_feature` query
* @param {string} fieldName Name of the field inside the document
* @returns {RankFeatureQuery} Instance of the distance feature query
*/
field(fieldName) {
this._queryOpts.field = fieldName;
return this;
}

/**
* Linear function to boost relevance scores based on the value of the rank feature field
* @returns {RankFeatureQuery}
*/
linear() {
this._queryOpts.linear = {};
return this;
}

/**
* Saturation function to boost relevance scores based on the value of the rank feature field.
* Uses a default pivot value computed by Elasticsearch.
* @returns {RankFeatureQuery}
*/
saturation() {
this._queryOpts.saturation = {};
return this;
}

/**
* Saturation function to boost relevance scores based on the value of the rank feature field.
* @param {number} pivot
* @returns {RankFeatureQuery}
*/
saturationPivot(pivot) {
this._queryOpts.saturation = {};
this._queryOpts.saturation.pivot = pivot;
return this;
}

/**
* The log function gives a score equal to log(scaling_factor + S), where S
* is the value of the rank feature field and scaling_factor is a configurable
* scaling factor.
* @param {number} scaling_factor
* @returns {RankFeatureQuery}
*/
log(scalingFactor) {
this._queryOpts.log = {};
this._queryOpts.log.scaling_factor = scalingFactor;
return this;
}

/**
* The sigmoid function extends the saturation function with a configurable exponent.
* @param {number} pivot
* @param {number} exponent
* @returns {RankFeatureQuery}
*/
sigmoid(pivot, exponent) {
this._queryOpts.sigmoid = {};
this._queryOpts.sigmoid.pivot = pivot;
this._queryOpts.sigmoid.exponent = exponent;
return this;
}
}

module.exports = RankFeatureQuery;
86 changes: 86 additions & 0 deletions test/queries-test/rank-feature.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import test from 'ava';
import { RankFeatureQuery } from '../../src';

test('Should test no args rank feature query', t => {
const value = new RankFeatureQuery('my_field').toJSON();
const expected = {
rank_feature: {
field: 'my_field'
}
};
t.deepEqual(value, expected);
});

test('Should test with fieldName', t => {
const value = new RankFeatureQuery().field('my_field').toJSON();
const expected = {
rank_feature: {
field: 'my_field'
}
};
t.deepEqual(value, expected);
});

test('Should test linear rank feature query', t => {
const value = new RankFeatureQuery('my_field').linear().toJSON();
const expected = {
rank_feature: {
field: 'my_field',
linear: {}
}
};
t.deepEqual(value, expected);
});

test('Should test saturation rank feature query', t => {
const value = new RankFeatureQuery('my_field').saturation().toJSON();
const expected = {
rank_feature: {
field: 'my_field',
saturation: {}
}
};
t.deepEqual(value, expected);
});

test('Should test saturation with pivot rank feature query', t => {
const value = new RankFeatureQuery('my_field')
.saturationPivot(123)
.toJSON();
const expected = {
rank_feature: {
field: 'my_field',
saturation: {
pivot: 123
}
}
};
t.deepEqual(value, expected);
});

test('Should test sigmoid rank feature query', t => {
const value = new RankFeatureQuery('my_field').sigmoid(2, 0.6).toJSON();
const expected = {
rank_feature: {
field: 'my_field',
sigmoid: {
pivot: 2,
exponent: 0.6
}
}
};
t.deepEqual(value, expected);
});

test('Should test logarithmic rank feature query', t => {
const value = new RankFeatureQuery('my_field').log(2).toJSON();
const expected = {
rank_feature: {
field: 'my_field',
log: {
scaling_factor: 2
}
}
};
t.deepEqual(value, expected);
});

0 comments on commit 8002c89

Please sign in to comment.