Skip to content

Commit

Permalink
rm support for _packed fields
Browse files Browse the repository at this point in the history
  • Loading branch information
charmingduchess committed Dec 10, 2024
1 parent 547a271 commit a53bfbb
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 42 deletions.
14 changes: 7 additions & 7 deletions lib/elasticsearch/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
25 changes: 11 additions & 14 deletions lib/elasticsearch/elastic-query-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand All @@ -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 }
})
Expand All @@ -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
Expand Down
31 changes: 10 additions & 21 deletions test/elastic-query-builder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:
{
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit a53bfbb

Please sign in to comment.