I'm trying to implement a faceted search on my website that allows users to select multiple facets within a group, but it also needs to filter out irrelevant options in other facets based on selections. Here's the scenario:
- I have four active products, all categorized under 'Thermostats'.
- Users can filter these products by two facets: price (with options "$20 - $50", "$50 - $100", "$100 - $200", "$200 - $500") and product type (with options "Air Exchanger Accessories", "Digital Thermostat").
- If a user selects the "Air Exchanger Accessories" facet, only one product matches, priced between "$200 - $500". This selection should dynamically adjust the available price options to just "$200 - $500", while still displaying "Digital Thermostat" as an option for potential multi-selection.
I'm unsure if this can be achieved with a single query or if multiple queries and subsequent filtering are required.
Here is example data:
POST /_bulk
{"index": { "_index": "facet-test" }}
{"allAttributes":[{"atrKeys":["5"],"code":"price","type":"Price","values":["$200 -$500"]},{"atrKeys":["by1"],"code":"product_specifications","id":1329,"type":"Product Specifications","values":["Air Exchanger Accessories"]},{"atrKeys":["ecc"],"code":"product_category","id":14,"type":"Product Category","values":["Thermostats"]}],"isActive":true,"keyAttributes":["ecc","by1", "5"],"name":"Product 1"}
{"index": { "_index": "facet-test" }}
{"allAttributes":[{"atrKeys":["4"],"code":"price","type":"Price","values":["$100 - $200"]},{"atrKeys":["9w9"],"code":"product_specifications","id":1329,"type":"Product Specifications","values":["Digital Thermostat"]},{"atrKeys":["ecc"],"code":"product_category","id":14,"type":"Product Category","values":["Thermostats"]}],"isActive":true,"keyAttributes":["ecc","9w8", "4"],"name":"Product 1"}
{"index": { "_index": "facet-test" }}
{"allAttributes":[{"atrKeys":["3"],"code":"price","type":"Price","values":["$50 - $100"]},{"atrKeys":["9w9"],"code":"product_specifications","id":1329,"type":"Product Specifications","values":["Digital Thermostat"]},{"atrKeys":["ecc"],"code":"product_category","id":14,"type":"Product Category","values":["Thermostats"]}],"isActive":true,"keyAttributes":["ecc","9w8", "3"],"name":"Product 1"}
{"index": { "_index": "facet-test" }}
{"allAttributes":[{"atrKeys":["2"],"code":"price","type":"Price","values":["$20 - $50"]},{"atrKeys":["9w9"],"code":"product_specifications","id":1329,"type":"Product Specifications","values":["Digital Thermostat"]},{"atrKeys":["ecc"],"code":"product_category","id":14,"type":"Product Category","values":["Thermostats"]}],"isActive":true,"keyAttributes":["ecc","9w8", "2"],"name":"Product 1"}
Here is an example query that gets me close to what I want, however the invalid price options still appear in the aggregation.
POST /facet-test/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"isActive": true
}
},
{
"terms": {
"keyAttributes": [
"ecc"
]
}
}
]
}
},
"post_filter": {
"bool": {
"must": {
"term": {
"keyAttributes": "by1"
}
}
}
},
"size": 0,
"from": 0,
"aggs": {
"price": {
"nested": {
"path": "allAttributes"
},
"aggs": {
"price": {
"filter": {
"bool": {
"must": [
{
"term": {
"allAttributes.code": "price"
}
}
]
}
},
"aggs": {
"options": {
"terms": {
"field": "allAttributes.values",
"size": 100,
"order": {
"_term": "asc"
}
},
"meta": {
"name": "Price",
"description": "This is the price",
"inputType": "checkbox",
"priority": 1,
"units": "",
"tooltipIsLarge": ""
}
}
}
}
}
},
"attributes": {
"nested": {
"path": "allAttributes"
},
"aggs": {
"1329": {
"filter": {
"bool": {
"must": [
{
"term": {
"allAttributes.id": "1329"
}
},
{
"term": {
"allAttributes.code": "product_specifications"
}
}
]
}
},
"aggs": {
"options": {
"terms": {
"field": "allAttributes.values",
"size": 100,
"order": {
"_term": "asc"
}
}
}
}
}
}
}
}
}
The result is:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"price": {
"doc_count": 12,
"price": {
"doc_count": 4,
"options": {
"meta": {
"tooltipIsLarge": "",
"name": "Price",
"description": "This is the price",
"inputType": "checkbox",
"units": "",
"priority": 1
},
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "$100 - $200",
"doc_count": 1
},
{
"key": "$20 - $50",
"doc_count": 1
},
{
"key": "$200 -$500",
"doc_count": 1
},
{
"key": "$50 - $100",
"doc_count": 1
}
]
}
}
},
"attributes": {
"1329": {
"doc_count": 4,
"options": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Air Exchanger Accessories",
"doc_count": 1
},
{
"key": "Digital Thermostat",
"doc_count": 3
}
]
}
},
"doc_count": 12
}
}
}