@searchkit/sdk
Version:
Elasticsearch Universal SDK for Searchkit
122 lines (112 loc) • 3.05 kB
text/typescript
import { ValueFilter } from '../core/QueryManager'
import { BaseFacet } from './BaseFacet'
interface GeoDistanceOptionsFacetConfig {
identifier: string
field: string
origin: string
unit?: string
label: string
display?: string
ranges: {
from?: number
to?: number
label: string
}[]
multipleSelect?: boolean
}
class GeoDistanceOptionsFacet implements BaseFacet {
public excludeOwnFilters = false
private unit: string
constructor(public config: GeoDistanceOptionsFacetConfig) {
this.excludeOwnFilters = config.multipleSelect
this.unit = config.unit || 'mi'
}
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 }) => {
const range = this.config.ranges.find((option) => option.label === value)
return range
})
return {
bool: {
[condition]: filters.map((range) => ({
bool: {
...(range.from
? {
must_not: [
{
geo_distance: {
distance: range.from + this.config.unit,
[this.config.field]: this.config.origin
}
}
]
}
: {}),
...(range.to
? {
must: [
{
geo_distance: {
distance: range.to + this.config.unit,
[this.config.field]: this.config.origin
}
}
]
}
: {})
}
}))
}
}
}
getAggregation() {
return {
[this.getIdentifier()]: {
geo_distance: {
field: this.config.field,
origin: this.config.origin,
unit: this.unit,
keyed: true,
ranges: this.config.ranges.map((range) => ({
from: range.from,
to: range.to,
key: range.label
}))
}
}
}
}
getSelectedFilter(filterSet: ValueFilter) {
return {
identifier: this.getIdentifier(),
id: `${this.getIdentifier()}_${filterSet.value}`,
label: this.getLabel(),
display: this.config.display || 'ListFacet',
type: 'GeoDistanceOptionsFacet',
value: filterSet.value
}
}
transformResponse(response: any) {
return {
identifier: this.getIdentifier(),
label: this.getLabel(),
display: this.config.display || 'ListFacet',
type: 'GeoDistanceOptionsFacet',
entries: this.config.ranges.map((option) => {
const docCount = response.buckets[option.label]?.doc_count || 0
return {
label: option.label,
count: docCount
}
})
}
}
}
export default GeoDistanceOptionsFacet