From 9c5f253e5f67e21cefd7d82b4a84a9c61d20abdc Mon Sep 17 00:00:00 2001 From: Ian O'Connor Date: Mon, 6 Apr 2026 13:27:32 -0400 Subject: [PATCH 1/2] Include normalized prefix results in has search --- lib/elasticsearch/elastic-query-browse-builder.js | 1 + test/elastic-query-browse-builder.test.js | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/elasticsearch/elastic-query-browse-builder.js b/lib/elasticsearch/elastic-query-browse-builder.js index 36615241..b36ac29f 100644 --- a/lib/elasticsearch/elastic-query-browse-builder.js +++ b/lib/elasticsearch/elastic-query-browse-builder.js @@ -52,6 +52,7 @@ class ElasticQueryBrowseBuilder { this.query.addMust({ bool: { should: [ + { prefix: { 'preferredTerm.keyword_normalized': { value: this.request.querySansQuotes(), _name: 'preferredTermPrefix' } } }, { match: { preferredTerm: { query: this.request.querySansQuotes(), operator: 'and', _name: 'preferredTerm' } } }, { nested: { path: 'variants', query: { match: { 'variants.variant': { query: this.request.querySansQuotes(), operator: 'and' } } }, inner_hits: {} } } ] diff --git a/test/elastic-query-browse-builder.test.js b/test/elastic-query-browse-builder.test.js index e9830b07..b9685a1e 100644 --- a/test/elastic-query-browse-builder.test.js +++ b/test/elastic-query-browse-builder.test.js @@ -43,9 +43,14 @@ describe('ElasticQueryBrowseBuilder', () => { const query = inst.query.toJson() - expect(query.bool.must[0].bool.should.length).to.equal(2) + expect(query.bool.must[0].bool.should.length).to.equal(3) expect(query.bool.must[0].bool.should[0]) expect(query.bool.must[0].bool.should[0]).to.deep.equal({ + prefix: { + 'preferredTerm.keyword_normalized': { value: 'toast bread', _name: 'preferredTermPrefix' } + } + }) + expect(query.bool.must[0].bool.should[1]).to.deep.equal({ match: { preferredTerm: { _name: 'preferredTerm', @@ -55,7 +60,7 @@ describe('ElasticQueryBrowseBuilder', () => { } }) - expect(query.bool.must[0].bool.should[1]).to.deep.equal({ + expect(query.bool.must[0].bool.should[2]).to.deep.equal({ nested: { inner_hits: {}, path: 'variants', From 4ee5b937c9fc90159ae1ac8db2a844da325531e2 Mon Sep 17 00:00:00 2001 From: Ian O'Connor Date: Tue, 14 Apr 2026 16:05:41 -0400 Subject: [PATCH 2/2] Light normalization preprocessing for browse terms --- lib/elasticsearch/elastic-query-browse-builder.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/elasticsearch/elastic-query-browse-builder.js b/lib/elasticsearch/elastic-query-browse-builder.js index b36ac29f..08b47360 100644 --- a/lib/elasticsearch/elastic-query-browse-builder.js +++ b/lib/elasticsearch/elastic-query-browse-builder.js @@ -4,6 +4,7 @@ class ElasticQueryBrowseBuilder { constructor (apiRequest) { this.request = apiRequest this.query = new ElasticQuery() + this.normalizedQuery = this.request.querySansQuotes().normalize('NFC') switch (this.request.params.search_scope) { case 'has': @@ -24,8 +25,8 @@ class ElasticQueryBrowseBuilder { this.query.addMust({ bool: { should: [ - { prefix: { 'preferredTerm.keyword_normalized': { value: this.request.querySansQuotes(), _name: 'preferredTerm' } } }, - { nested: { path: 'variants', query: { prefix: { 'variants.variant.keyword_normalized': this.request.querySansQuotes() } }, inner_hits: {} } } + { prefix: { 'preferredTerm.keyword_normalized': { value: this.normalizedQuery, _name: 'preferredTerm' } } }, + { nested: { path: 'variants', query: { prefix: { 'variants.variant.keyword_normalized': this.normalizedQuery } }, inner_hits: {} } } ] } }) @@ -38,8 +39,8 @@ class ElasticQueryBrowseBuilder { this.query.addMust({ bool: { should: [ - { term: { 'preferredTerm.keyword': { value: this.request.querySansQuotes(), _name: 'preferredTerm' } } }, - { nested: { path: 'variants', query: { term: { 'variants.variant.keyword': this.request.querySansQuotes() } }, inner_hits: {} } } + { term: { 'preferredTerm.keyword': { value: this.normalizedQuery, _name: 'preferredTerm' } } }, + { nested: { path: 'variants', query: { term: { 'variants.variant.keyword': this.normalizedQuery } }, inner_hits: {} } } ] } }) @@ -52,9 +53,9 @@ class ElasticQueryBrowseBuilder { this.query.addMust({ bool: { should: [ - { prefix: { 'preferredTerm.keyword_normalized': { value: this.request.querySansQuotes(), _name: 'preferredTermPrefix' } } }, - { match: { preferredTerm: { query: this.request.querySansQuotes(), operator: 'and', _name: 'preferredTerm' } } }, - { nested: { path: 'variants', query: { match: { 'variants.variant': { query: this.request.querySansQuotes(), operator: 'and' } } }, inner_hits: {} } } + { prefix: { 'preferredTerm.keyword_normalized': { value: this.normalizedQuery, _name: 'preferredTermPrefix' } } }, + { match: { preferredTerm: { query: this.normalizedQuery, operator: 'and', _name: 'preferredTerm' } } }, + { nested: { path: 'variants', query: { match: { 'variants.variant': { query: this.normalizedQuery, operator: 'and' } } }, inner_hits: {} } } ] } })