@searchkit/sdk
Version:
Elasticsearch Universal SDK for Searchkit
118 lines (107 loc) • 2.85 kB
text/typescript
import { ValueFilter } from '../core/QueryManager'
import { BaseFacet } from './BaseFacet'
interface MultiQueryOptionsFacetConfig {
identifier: string
field: string
label: string
display?: string
options: {
min?: number
max?: number
value?: string | number
dateMin?: string
dateMax?: string
label: string
}[]
multipleSelect?: boolean
}
const filterClauseMapper = (field) => (option) => {
if (option.min || option.max) {
return {
range: {
[field]: {
...(option.min && { gte: option.min }),
...(option.max && { lte: option.max })
}
}
}
} else if (option.value) {
return {
term: {
[field]: option.value
}
}
} else if (option.dateMin || option.dateMax) {
return {
range: {
[field]: {
...(option.dateMin && { gte: option.dateMin }),
...(option.dateMax && { lte: option.dateMax })
}
}
}
}
}
class MultiQueryOptionsFacet implements BaseFacet {
public excludeOwnFilters = false
constructor(public config: MultiQueryOptionsFacetConfig) {
this.excludeOwnFilters = config.multipleSelect
}
getLabel(): string {
return this.config.label
}
getIdentifier(): string {
return this.config.identifier
}
getFilters(filterValues: ValueFilter[]) {
const condition = this.excludeOwnFilters ? 'should' : 'must'
const filters = filterValues
.map((value) => this.config.options.find((option) => option.label === value.value))
.filter((option) => !!option)
return {
bool: {
[condition]: filters.map(filterClauseMapper(this.config.field))
}
}
}
getAggregation() {
const filterClauses = this.config.options.map(filterClauseMapper(this.config.field))
const filters = this.config.options.reduce((acc, option, i) => {
acc[option.label] = filterClauses[i]
return acc
}, {})
return {
[this.getIdentifier()]: {
filters: {
filters: filters
}
}
}
}
getSelectedFilter(filterSet: ValueFilter) {
return {
identifier: this.getIdentifier(),
id: `${this.getIdentifier()}_${filterSet.value}`,
label: this.getLabel(),
display: this.config.display || 'ListFacet',
type: 'MultiQueryOptionsFacet',
value: filterSet.value
}
}
transformResponse(response: any) {
return {
identifier: this.getIdentifier(),
label: this.getLabel(),
display: this.config.display || 'ListFacet',
type: 'MultiQueryOptionsFacet',
entries: this.config.options.map((option) => {
const docCount = response.buckets[option.label]?.doc_count || 0
return {
label: option.label,
count: docCount
}
})
}
}
}
export default MultiQueryOptionsFacet