diff --git a/lib/elasticsearch/config.js b/lib/elasticsearch/config.js index d050ef6..84314ac 100644 --- a/lib/elasticsearch/config.js +++ b/lib/elasticsearch/config.js @@ -75,18 +75,18 @@ const SEARCH_SCOPES = { const FILTER_CONFIG = { recordType: { operator: 'match', field: ['recordTypeId'], repeatable: true }, - owner: { operator: 'match', field: ['items.owner_packed'], repeatable: true, path: 'items' }, + owner: { operator: 'match', field: ['items.owner.id', 'items.owner.label'], repeatable: true, path: 'items' }, subjectLiteral: { operator: 'match', field: ['subjectLiteral_exploded'], repeatable: true }, - holdingLocation: { operator: 'match', field: ['items.holdingLocation_packed'], repeatable: true, path: 'items' }, + holdingLocation: { operator: 'match', field: ['items.holdingLocation.id', 'items.holdingLocation.label'], repeatable: true, path: 'items' }, buildingLocation: { operator: 'match', field: ['buildingLocationIds'], repeatable: true }, - language: { operator: 'match', field: ['language_packed'], repeatable: true }, - materialType: { operator: 'match', field: ['materialType_packed'], repeatable: true }, - mediaType: { operator: 'match', field: ['mediaType_packed'], repeatable: true }, - carrierType: { operator: 'match', field: ['carrierType_packed'], repeatable: true }, + language: { operator: 'match', field: ['language.id', 'language.label'], repeatable: true }, + materialType: { operator: 'match', field: ['materialType.id', 'materialType.label'], repeatable: true }, + mediaType: { operator: 'match', field: ['mediaType.id', 'mediaType.label'], repeatable: true }, + carrierType: { operator: 'match', field: ['carrierType.id', 'carrierType.label'], repeatable: true }, publisher: { operator: 'match', field: ['publisherLiteral.raw'], repeatable: true }, contributorLiteral: { operator: 'match', field: ['contributorLiteral.raw'], repeatable: true }, creatorLiteral: { operator: 'match', field: ['creatorLiteral.raw', 'parallelCreatorLiteral.raw'], repeatable: true }, - issuance: { operator: 'match', field: ['issuance_packed'], repeatable: true }, + issuance: { operator: 'match', field: ['issuance.id', 'issuance.label'], repeatable: true }, createdYear: { operator: 'match', field: ['createdYear'], repeatable: true }, dateAfter: { operator: 'custom', diff --git a/lib/elasticsearch/elastic-query-builder.js b/lib/elasticsearch/elastic-query-builder.js index 338b9ba..e1788a4 100644 --- a/lib/elasticsearch/elastic-query-builder.js +++ b/lib/elasticsearch/elastic-query-builder.js @@ -510,21 +510,18 @@ class ElasticQueryBuilder { } // This builds a filter cause from the value: - buildClause (value, field) { - const filterMatchesOnMoreThanOneField = field.length > 1 + buildFilterClause (value, fieldsToMatchOn) { + const filterMatchesOnMoreThanOneField = fieldsToMatchOn.length > 1 if (filterMatchesOnMoreThanOneField) { - return this.buildMultiFieldClause(value, field) + return this.buildMultiFieldClause(value, fieldsToMatchOn) + } else { + const field = fieldsToMatchOn[0] + return { term: { [field]: value } } } - field = field[0] - const valueIsNotPackedValue = value.indexOf('||') < 0 - const isPackedField = field.match(/_packed$/) - if (isPackedField && valueIsNotPackedValue) { - return this.buildPackedFieldClause(value, field) - } else return { term: { [field]: value } } } - buildSimpleMatchFilters (simpleMatchFilters) { - return simpleMatchFilters.map((prop) => { + buildMatchOperatorFilterQueries (filtersWithMatchOperators) { + return filtersWithMatchOperators.map((prop) => { const config = FILTER_CONFIG[prop] let value = this.request.params.filters[prop] @@ -533,7 +530,7 @@ class ElasticQueryBuilder { const booleanOperator = 'should' if (Array.isArray(value) && value.length === 1) value = value.shift() - const clause = (Array.isArray(value)) ? { bool: { [booleanOperator]: value.map((value) => this.buildClause(value, config.field)) } } : this.buildClause(value, config.field) + const clause = (Array.isArray(value)) ? { bool: { [booleanOperator]: value.map((value) => this.buildFilterClause(value, config.field)) } } : this.buildFilterClause(value, config.field) return { path: config.path, clause } }) @@ -553,10 +550,10 @@ class ElasticQueryBuilder { ) // Collect those filters that use a simple term match - const simpleMatchFilters = Object.keys(this.request.params.filters) + const filtersWithMatchOperators = Object.keys(this.request.params.filters) .filter((k) => FILTER_CONFIG[k].operator === 'match') - filterClausesWithPaths = filterClausesWithPaths.concat(this.buildSimpleMatchFilters(simpleMatchFilters)) + filterClausesWithPaths = filterClausesWithPaths.concat(this.buildMatchOperatorFilterQueries(filtersWithMatchOperators)) // Gather root (not nested) filters: let filterClauses = filterClausesWithPaths diff --git a/test/elastic-query-builder.test.js b/test/elastic-query-builder.test.js index 2f5ca13..d8b4212 100644 --- a/test/elastic-query-builder.test.js +++ b/test/elastic-query-builder.test.js @@ -4,9 +4,9 @@ const ElasticQueryBuilder = require('../lib/elasticsearch/elastic-query-builder' const ApiRequest = require('../lib/api-request') describe('ElasticQueryBuilder', () => { - describe('buildClause', () => { + describe('buildFilterClause', () => { it('can handle multiple fields', () => { - expect(ElasticQueryBuilder.prototype.buildClause('value', ['field', 'parallelField'])) + expect(ElasticQueryBuilder.prototype.buildFilterClause('value', ['field', 'parallelField'])) .to.deep.equal({ bool: { @@ -16,34 +16,23 @@ describe('ElasticQueryBuilder', () => { } }) }) - it('can handle packed fields', () => { - expect(ElasticQueryBuilder.prototype.buildClause('not packed value', ['field_packed'])) - .to.deep.equal({ - bool: { - should: [ - { term: { 'field.id': 'not packed value' } }, - { term: { 'field.label': 'not packed value' } } - ] - } - }) - }) it('can handle the simple case', () => { - expect(ElasticQueryBuilder.prototype.buildClause('value', ['field'])) + expect(ElasticQueryBuilder.prototype.buildFilterClause('value', ['field'])) .to.deep.equal({ term: { field: 'value' } }) }) }) - describe('buildSimpleMatchFilters', () => { + describe('buildMatchOperatorFilterQueries', () => { const mockQueryBuilderFactory = (request) => ({ request, buildMultiFieldClause: ElasticQueryBuilder.prototype.buildMultiFieldClause, - buildSimpleMatchFilters: ElasticQueryBuilder.prototype.buildSimpleMatchFilters, - buildClause: ElasticQueryBuilder.prototype.buildClause, + buildMatchOperatorFilterQueries: ElasticQueryBuilder.prototype.buildMatchOperatorFilterQueries, + buildFilterClause: ElasticQueryBuilder.prototype.buildFilterClause, buildPackedFieldClause: ElasticQueryBuilder.prototype.buildPackedFieldClause }) it('can handle (multiple) single value, single match field filters, as arrays', () => { const request = new ApiRequest({ filters: { buildingLocation: ['toast'], subjectLiteral: ['spaghetti'] } }) const mockQueryBuilder = mockQueryBuilderFactory(request) - const simpleMatchFilters = mockQueryBuilder.buildSimpleMatchFilters(['buildingLocation', 'subjectLiteral']) + const simpleMatchFilters = mockQueryBuilder.buildMatchOperatorFilterQueries(['buildingLocation', 'subjectLiteral']) expect(simpleMatchFilters).to.deep.equal([ { path: undefined, @@ -58,7 +47,7 @@ describe('ElasticQueryBuilder', () => { it('can handle (multiple) single value, single match field filters, strings', () => { const request = new ApiRequest({ filters: { buildingLocation: 'toast', subjectLiteral: 'spaghetti' } }) const mockQueryBuilder = mockQueryBuilderFactory(request) - const simpleMatchFilters = mockQueryBuilder.buildSimpleMatchFilters(['buildingLocation', 'subjectLiteral']) + const simpleMatchFilters = mockQueryBuilder.buildMatchOperatorFilterQueries(['buildingLocation', 'subjectLiteral']) expect(simpleMatchFilters).to.deep.equal([ { path: undefined, @@ -73,7 +62,7 @@ describe('ElasticQueryBuilder', () => { it('can handle multiple values', () => { const request = new ApiRequest({ filters: { subjectLiteral: ['spaghetti', 'meatballs'] } }) const mockQueryBuilder = mockQueryBuilderFactory(request) - const simpleMatchFilters = mockQueryBuilder.buildSimpleMatchFilters(['subjectLiteral']) + const simpleMatchFilters = mockQueryBuilder.buildMatchOperatorFilterQueries(['subjectLiteral']) expect(simpleMatchFilters).to.deep.equal([ { path: undefined, @@ -91,7 +80,7 @@ describe('ElasticQueryBuilder', () => { it('can handle packed values', () => { const request = new ApiRequest({ filters: { language: ['spanish', 'finnish'] } }) const mockQueryBuilder = mockQueryBuilderFactory(request) - const simpleMatchFilters = mockQueryBuilder.buildSimpleMatchFilters(['language']) + const simpleMatchFilters = mockQueryBuilder.buildMatchOperatorFilterQueries(['language']) expect(simpleMatchFilters).to.deep.equal([ { path: undefined,