I want to implement facet filters on my products list page using elasticsearch. Basically my product document index contains a number of products which contains a number of variations.
The variations are defines as "nested" objects in order to make sure only products are returned where a variation matches all filter criteria. The filtering the variations seems to work correct. However the facets results are not as I would expect a facet filter to work.
For example my query below returns the terms "oriental" and "citrus" for the facet "f_attribute_scent". However I only want to get back the term that matched my filter which would be "citrus".
I have tried out a lot of different things with facet filters and everything but I just can't get it to work correctly.
My mapping looks like this:
curl -XPOST localhost:9200/products -d '
{
"mappings": {
"de": {
"properties": {
"variants": {
"type": "nested",
"include_in_parent": true
}
}
}
}
}
'
Here is my test data:
curl -XPUT localhost:9200/products/de/12 -d '
{
"id": "12",
"categories": [
{
"id": "12345",
"sort": "1"
},
{
"id": "23456",
"sort": "2"
},
{
"id": "34567",
"sort": "3"
}
],
"variants": [
{
"id": "12.1.1",
"brand": "guerlain",
"collection": "emporio",
"rating": 4,
"color": "green",
"price": 31,
"scent": "fruity"
},
{
"id": "12.1.2",
"brand": "guerlain",
"collection": "emporio",
"rating": 2,
"color": "blue",
"price": 49.99,
"scent": "flowery"
}
]
}'
curl -XPUT localhost:9200/products/de/15 -d '
{
"id": "15",
"categories": [
{
"id": "12345",
"sort": "1"
},
{
"id": "23456",
"sort": "2"
},
{
"id": "34567",
"sort": "3"
}
],
"variants": [
{
"id": "15.1.1",
"brand": "dior",
"collection": "foobar",
"rating": 4,
"color": "green",
"price": 48.00,
"scent": "oriental"
},
{
"id": "15.1.2",
"brand": "dior",
"collection": "foobar",
"rating": 2,
"color": "red",
"price": 52,
"scent": "citrus"
}
]
}'
This is the query:
curl -XGET localhost:9200/products/de/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "variants",
"filter": {
"bool": {
"must": [
{
"terms": {
"variants.color": [
"green",
"red"
]
}
},
{
"term": {
"variants.scent": "citrus"
}
}
]
}
}
}
}
}
},
"facets": {
"f_attribute_color": {
"terms": {
"all_terms": true,
"field": "variants.color"
}
},
"f_attribute_scent": {
"terms": {
"field": "variants.scent"
}
}
}
}
... And the result:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "products",
"_type": "de",
"_id": "15",
"_score": 1,
"_source": {
"id": "15",
"categories": [
{
"id": "12345",
"sort": "1"
},
{
"id": "23456",
"sort": "2"
},
{
"id": "34567",
"sort": "3"
}
],
"variants": [
{
"id": "15.1.1",
"brand": "dior",
"collection": "foobar",
"rating": 4,
"color": "green",
"price": 48,
"scent": "oriental"
},
{
"id": "15.1.2",
"brand": "dior",
"collection": "foobar",
"rating": 2,
"color": "red",
"price": 52,
"scent": "citrus"
}
]
}
}
]
},
"facets": {
"f_attribute_color": {
"_type": "terms",
"missing": 0,
"total": 2,
"other": 0,
"terms": [
{
"term": "red",
"count": 1
},
{
"term": "green",
"count": 1
}
]
},
"f_attribute_scent": {
"_type": "terms",
"missing": 0,
"total": 2,
"other": 0,
"terms": [
{
"term": "oriental",
"count": 1
},
{
"term": "citrus",
"count": 1
}
]
}
}
}