Update elasticsearch translator to handle phrase searches. (#27720)
* Update elasticsearch translator to handle phrase searches. Signed-off-by: Sydney Achinger <sydneynicoleachinger@spotify.com> * Add helpful regex comment Co-authored-by: John Philip <johnphilip283@gmail.com> Signed-off-by: Sydney Achinger <78113809+squid-ney@users.noreply.github.com> --------- Signed-off-by: Sydney Achinger <sydneynicoleachinger@spotify.com> Signed-off-by: Sydney Achinger <78113809+squid-ney@users.noreply.github.com> Co-authored-by: John Philip <johnphilip283@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-module-elasticsearch': patch
|
||||
---
|
||||
|
||||
Update the ElasticSearchSearchEngine translator to handle phrase searches.
|
||||
+58
-14
@@ -185,12 +185,11 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
expect(queryBody).toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
must: {
|
||||
should: {
|
||||
multi_match: {
|
||||
query: 'testTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
@@ -205,6 +204,56 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return translated query with phrase terms', async () => {
|
||||
const translatorUnderTest = inspectableSearchEngine.getTranslator();
|
||||
|
||||
const actualTranslatedQuery = translatorUnderTest({
|
||||
types: ['indexName'],
|
||||
term: '"test phrase" anotherTerm "another phrase"',
|
||||
filters: {},
|
||||
}) as ElasticSearchConcreteQuery;
|
||||
|
||||
expect(actualTranslatedQuery).toMatchObject({
|
||||
documentTypes: ['indexName'],
|
||||
elasticSearchQuery: expect.any(Object),
|
||||
});
|
||||
|
||||
const queryBody = actualTranslatedQuery.elasticSearchQuery;
|
||||
|
||||
expect(queryBody).toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
multi_match: {
|
||||
query: 'test phrase',
|
||||
fields: ['*'],
|
||||
type: 'phrase',
|
||||
},
|
||||
},
|
||||
{
|
||||
multi_match: {
|
||||
query: 'another phrase',
|
||||
fields: ['*'],
|
||||
type: 'phrase',
|
||||
},
|
||||
},
|
||||
{
|
||||
multi_match: {
|
||||
query: 'anotherTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
},
|
||||
},
|
||||
],
|
||||
filter: [],
|
||||
},
|
||||
},
|
||||
from: 0,
|
||||
size: 25,
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass page cursor', async () => {
|
||||
const translatorUnderTest = inspectableSearchEngine.getTranslator();
|
||||
|
||||
@@ -225,12 +274,11 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [],
|
||||
must: {
|
||||
should: {
|
||||
multi_match: {
|
||||
query: 'testTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -264,12 +312,11 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
expect(queryBody).toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
must: {
|
||||
should: {
|
||||
multi_match: {
|
||||
query: 'testTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
filter: [
|
||||
@@ -320,12 +367,11 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
expect(queryBody).toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
must: {
|
||||
should: {
|
||||
multi_match: {
|
||||
query: 'testTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
@@ -382,12 +428,11 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [],
|
||||
must: {
|
||||
should: {
|
||||
multi_match: {
|
||||
query: 'testTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -708,12 +753,11 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
must: {
|
||||
should: {
|
||||
multi_match: {
|
||||
query: 'testTerm',
|
||||
fields: ['*'],
|
||||
fuzziness: 'auto',
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
filter: [],
|
||||
@@ -747,7 +791,7 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
must: {
|
||||
should: {
|
||||
match_all: {},
|
||||
},
|
||||
filter: [],
|
||||
@@ -782,7 +826,7 @@ describe('ElasticSearchSearchEngine', () => {
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
must: {
|
||||
should: {
|
||||
match_all: {},
|
||||
},
|
||||
filter: [],
|
||||
|
||||
+29
-7
@@ -246,18 +246,40 @@ export class ElasticSearchSearchEngine implements SearchEngine {
|
||||
'Failed to add filters to query. Unrecognized filter type',
|
||||
);
|
||||
});
|
||||
const esbQuery = isBlank(term)
|
||||
? esb.matchAllQuery()
|
||||
: esb
|
||||
.multiMatchQuery(['*'], term)
|
||||
.fuzziness('auto')
|
||||
.minimumShouldMatch(1);
|
||||
|
||||
const esbQueries = [];
|
||||
// https://regex101.com/r/Lr0MqS/1
|
||||
const phraseTerms = term.match(/"[^"]*"/g);
|
||||
|
||||
if (isBlank(term)) {
|
||||
const esbQuery = esb.matchAllQuery();
|
||||
esbQueries.push(esbQuery);
|
||||
} else if (phraseTerms && phraseTerms.length > 0) {
|
||||
let restTerm = term;
|
||||
for (const phraseTerm of phraseTerms) {
|
||||
restTerm = restTerm.replace(phraseTerm, '');
|
||||
const esbPhraseQuery = esb
|
||||
.multiMatchQuery(['*'], phraseTerm.replace(/"/g, ''))
|
||||
.type('phrase');
|
||||
esbQueries.push(esbPhraseQuery);
|
||||
}
|
||||
if (restTerm?.length > 0) {
|
||||
const esbRestQuery = esb
|
||||
.multiMatchQuery(['*'], restTerm.trim())
|
||||
.fuzziness('auto');
|
||||
esbQueries.push(esbRestQuery);
|
||||
}
|
||||
} else {
|
||||
const esbQuery = esb.multiMatchQuery(['*'], term).fuzziness('auto');
|
||||
esbQueries.push(esbQuery);
|
||||
}
|
||||
|
||||
const pageSize = query.pageLimit || 25;
|
||||
const { page } = decodePageCursor(pageCursor);
|
||||
|
||||
let esbRequestBodySearch = esb
|
||||
.requestBodySearch()
|
||||
.query(esb.boolQuery().filter(filter).must([esbQuery]))
|
||||
.query(esb.boolQuery().filter(filter).should(esbQueries))
|
||||
.from(page * pageSize)
|
||||
.size(pageSize);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user