我想使用elasticsearch在我的产品列表页面上实现构面过滤器。 基本上我的产品文档索引包含许多产品,其中包含许多变体。
将变体定义为“嵌套”对象,以确保仅在变体与所有过滤条件匹配的情况下返回产品。 过滤变化似乎是正确的。然而,facets结果并不像我期望的一样,可以使用构面过滤器。
例如,我的查询返回了facet“f_attribute_scent”的术语“东方”和“柑橘”。但是我只想找回与我的过滤器匹配的术语,即“柑橘”。
我已尝试使用facet过滤器和其他所有内容,但我无法让它正常工作。
我的映射如下所示:
curl -XPOST localhost:9200/products -d '
{
"mappings": {
"de": {
"properties": {
"variants": {
"type": "nested",
"include_in_parent": true
}
}
}
}
}
'
这是我的测试数据:
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"
}
]
}'
这是查询:
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"
}
}
}
}
......结果:
{
"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
}
]
}
}
}
答案 0 :(得分:1)
根据您正在编制索引的上述数据示例,您会看到citrus
和oriental
作为术语方面的结果,因为您的文档有variants
作为数组以及这两个术语对于与您的查询匹配的文档有效。
来自Elasticsearch Facets Documentation:
要记住一个重要的区别。虽然搜索查询限制了返回的文档和构面计数,但搜索过滤器仅限制返回的文档 - 但不限制构面计数。
如果您需要限制文档和构面,并且您不愿意或无法使用查询,则可以使用构面过滤器。
根据您要求的文档和所需结果,您可能需要考虑使用Filter Facet。
答案 1 :(得分:1)
您的嵌套文档有两种方式编制索引:
variants
数组中每个元素一个,de
文档中的variants
字段设置为object
类型上述(2)的原因是您将include_in_parent
设置为true
。实际上,顶级文档看起来像:
{
"id": "12",
"variants.id": [ "12.1.1","12.1.2"],
"variants.brand": [ "guerlain", "guerlain"],
"variants.color": [ "green", "blue"]
... etc ...
}
您的查询正确使用了nested
过滤器,该过滤器标识了匹配的顶级文档,但是您可以在顶级文档上进行操作,而不是嵌套文档,这就是您获得所有结果的原因
要解决此问题,您需要做的就是更改您的方面以改为使用嵌套文档
将您在主查询中使用的相同嵌套过滤器添加为facet_filter
:
"facets": {
"f_attribute_color": {
"terms": {
"field": "variants.color"
},
"nested": "variants",
"facet_filter": {
"bool": {
"must": [
{
"terms": {
"variants.color": [
"green",
"red"
]
}
},
{
"term": {
"variants.scent": "citrus"
}
}
]
}
}
},
"f_attribute_scent": {
"terms": {
"field": "variants.scent"
},
"nested": "variants",
"facet_filter": {
"bool": {
"must": [
{
"terms": {
"variants.color": [
"green",
"red"
]
}
},
{
"term": {
"variants.scent": "citrus"
}
}
]
}
}
}
}
答案 2 :(得分:0)
你是对的:如果我使用你的过滤器面,我只会被退回"柑橘"为了"香味"小面。
但是,如果我想按品牌名称过滤" dior"我又遇到了同样的问题。方面结果返回" dior"计数为" 2"。原因是现在两种变体都有相同的品牌名称:
GET /products/de/_search
{
"filter": {
"nested": {
"path": "variants",
"filter": {
"bool": {
"must": [
{
"term": {
"variants.brand": "dior"
}
}
]
}
}
}
},
"facets": {
"f_attribute_brand": {
"nested": "variants",
"facet_filter": {
"bool": {
"must": [
{
"term": {
"variants.brand": "dior"
}
}
]
}
},
"terms": {
"field": "variants.brand"
}
}
}
}
结果:
{
"took": 3,
"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
}
]
},
"facets": {
"f_attribute_brand": {
"_type": "terms",
"missing": 0,
"total": 2,
"other": 0,
"terms": [
{
"term": "dior",
"count": 2
}
]
}
}
}