From 05c06a6b178f037ce76af4bc6fc0457cd1654316 Mon Sep 17 00:00:00 2001 From: VexedElm035 Date: Tue, 23 Sep 2025 16:50:19 -0600 Subject: [PATCH 1/3] Add Semantic Vector Query --- src/index.d.ts | 22 ++++ src/index.js | 5 +- src/queries/vector-queries/index.js | 1 + src/queries/vector-queries/semantic-query.js | 49 +++++++++ test/index.test.js | 3 + test/queries-test/semantic-query.test.js | 107 +++++++++++++++++++ 6 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/queries/vector-queries/semantic-query.js create mode 100644 test/queries-test/semantic-query.test.js diff --git a/src/index.d.ts b/src/index.d.ts index 71140b3..ccb6020 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -3858,6 +3858,28 @@ declare namespace esb { field? : string ) : SparseVectorQuery; + /** + * The `semantic` query enables semantic search on a `semantic_text` field. + * + * NOTE: Only available in Elasticsearch v9.0+ + * + * @param {string=} field The semantic_text field to query. + * @param {string=} query The semantic query text. + * @extends Query + */ + export class SemanticQuery extends Query {} + + /** + * Creates a `semantic` query. + * + * @param {string=} field The semantic_text field to query. + * @param {string=} query The semantic query text. + */ + export function semanticQuery( + field?: string, + query?: string + ): SemanticQuery; + /** * Knn performs k-nearest neighbor (KNN) searches. * This class allows configuring the KNN search with various parameters such as field, query vector, diff --git a/src/index.js b/src/index.js index 4d1e056..21bddfc 100644 --- a/src/index.js +++ b/src/index.js @@ -90,7 +90,7 @@ const { SpanWithinQuery, SpanFieldMaskingQuery }, - vectorQueries: { SparseVectorQuery } + vectorQueries: { SparseVectorQuery, SemanticQuery } } = require('./queries'); const { @@ -349,6 +349,9 @@ exports.spanFieldMaskingQuery = constructorWrapper(SpanFieldMaskingQuery); exports.SparseVectorQuery = SparseVectorQuery; exports.sparseVectorQuery = constructorWrapper(SparseVectorQuery); +exports.SemanticQuery = SemanticQuery; +exports.semanticQuery = constructorWrapper(SemanticQuery); + /* ============ ============ ============ */ /* ======== KNN ======== */ /* ============ ============ ============ */ diff --git a/src/queries/vector-queries/index.js b/src/queries/vector-queries/index.js index ea1df30..527cc3e 100644 --- a/src/queries/vector-queries/index.js +++ b/src/queries/vector-queries/index.js @@ -1,3 +1,4 @@ 'use strict'; exports.SparseVectorQuery = require('./sparse-vector-query'); +exports.SemanticQuery = require('./semantic-query'); diff --git a/src/queries/vector-queries/semantic-query.js b/src/queries/vector-queries/semantic-query.js new file mode 100644 index 0000000..ec98099 --- /dev/null +++ b/src/queries/vector-queries/semantic-query.js @@ -0,0 +1,49 @@ +'use strict'; + +const { Query } = require('../../core'); +const { isNil } = require('lodash'); + +/** + * The semantic query enables you to perform semantic search on data stored in a semantic_text field. + * Semantic search uses dense vector representations to capture the meaning and context of search terms, + * providing more relevant results compared to traditional keyword-based search methods. + * + * Requires Elasticsearch v9.0+ (Stack 9 / Serverless) where the `semantic` query is available. + * + * [Elasticsearch reference](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-semantic-query) + * + * @example + * const qry = esb.semanticQuery('title_semantic', 'mountain lake').boost(2); + * + * @extends Query + */ +class SemanticQuery extends Query { + // eslint-disable-next-line require-jsdoc + constructor(field, query) { + super('semantic'); + if (!isNil(field)) this._queryOpts.field = field; + if (!isNil(query)) this._queryOpts.query = query; + } + + /** + * Sets the semantic field to query. + * @param {string} field The `semantic_text` field name. + * @returns {SemanticQuery} + */ + field(field) { + this._queryOpts.field = field; + return this; + } + + /** + * Sets the semantic query text. + * @param {string} query The query text. + * @returns {SemanticQuery} + */ + query(query) { + this._queryOpts.query = query; + return this; + } +} + +module.exports = SemanticQuery; diff --git a/test/index.test.js b/test/index.test.js index a0d2e4b..e45f894 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -175,6 +175,9 @@ test('queries are exported', t => { t.truthy(esb.sparseVectorQuery()); t.truthy(esb.SparseVectorQuery); + + t.truthy(esb.semanticQuery()); + t.truthy(esb.SemanticQuery); }); test('aggregations are exported', t => { diff --git a/test/queries-test/semantic-query.test.js b/test/queries-test/semantic-query.test.js new file mode 100644 index 0000000..b18865e --- /dev/null +++ b/test/queries-test/semantic-query.test.js @@ -0,0 +1,107 @@ +import test from 'ava'; +import esb, { SemanticQuery } from '../../src'; + +test('constructor sets field and query correctly', t => { + const q = new SemanticQuery('inference_field', 'Best surfing places'); + + const expected = { + semantic: { + field: 'inference_field', + query: 'Best surfing places' + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('empty constructor allows method chaining', t => { + const q = new SemanticQuery(); + q.field('inference_field').query('Best surfing places'); + + const expected = { + semantic: { + field: 'inference_field', + query: 'Best surfing places' + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('field method sets field correctly', t => { + const q = new SemanticQuery(); + q.field('title_semantic'); + + const expected = { + semantic: { + field: 'title_semantic' + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('query method sets query text correctly', t => { + const q = new SemanticQuery(); + q.query('mountain lake'); + + const expected = { + semantic: { + query: 'mountain lake' + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('supports boost parameter', t => { + const q = new SemanticQuery('title_semantic', 'mountain lake'); + q.boost(2); + + const expected = { + semantic: { + field: 'title_semantic', + query: 'mountain lake', + boost: 2 + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('call semantic query via esb factory function', t => { + const q = esb.semanticQuery('inference_field', 'Best surfing places'); + + const expected = { + semantic: { + field: 'inference_field', + query: 'Best surfing places' + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('call semantic query via esb factory function with chaining', t => { + const q = esb + .semanticQuery() + .field('semantic_field') + .query('shoes') + .boost(1.5); + + const expected = { + semantic: { + field: 'semantic_field', + query: 'shoes', + boost: 1.5 + } + }; + t.deepEqual(q.toJSON(), expected); +}); + +test('overwriting field and query works correctly', t => { + const q = new SemanticQuery('old_field', 'old query'); + q.field('new_field').query('new query'); + + const expected = { + semantic: { + field: 'new_field', + query: 'new query' + } + }; + t.deepEqual(q.toJSON(), expected); +}); From 1760ac77f540d7d79375858ff0c0c7fb2d95e5d2 Mon Sep 17 00:00:00 2001 From: VexedElm035 Date: Sat, 27 Sep 2025 07:16:58 -0600 Subject: [PATCH 2/3] add SemanticQuery constructor and methods --- src/index.d.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/index.d.ts b/src/index.d.ts index ccb6020..70dae97 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -3867,7 +3867,27 @@ declare namespace esb { * @param {string=} query The semantic query text. * @extends Query */ - export class SemanticQuery extends Query {} + export class SemanticQuery extends Query { + /** + * @param {string=} field The semantic_text field to query. + * @param {string=} query The semantic query text. + */ + constructor(field?: string, query?: string); + + /** + * Sets the semantic field to query. + * + * @param {string} field The `semantic_text` field name. + */ + field(field: string): this; + + /** + * Sets the semantic query text. + * + * @param {string} query The query text. + */ + query(query: string): this; + } /** * Creates a `semantic` query. From bc821b4d6d1388ec678983946e39d0b719ec1c52 Mon Sep 17 00:00:00 2001 From: Suhas Karanth Date: Sun, 28 Sep 2025 19:09:44 +0530 Subject: [PATCH 3/3] Update src/index.d.ts --- src/index.d.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/index.d.ts b/src/index.d.ts index 70dae97..c24ed48 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -3868,10 +3868,6 @@ declare namespace esb { * @extends Query */ export class SemanticQuery extends Query { - /** - * @param {string=} field The semantic_text field to query. - * @param {string=} query The semantic query text. - */ constructor(field?: string, query?: string); /**