运行Elasticsearch的5.4版。
使用此映射:
PUT pizzas
{
"mappings": {
"pizza": {
"properties": {
"name": {
"type": "keyword"
},
"types": {
"type": "nested",
"properties": {
"topping": {
"type": "keyword"
},
"base": {
"type": "keyword"
}
}
}
}
}
}
}
这个数据:
PUT pizzas/pizza/1
{
"name": "meat",
"types": [
{
"topping": "bacon",
"base": "normal"
},
{
"topping": "bacon",
"base": "sour dough"
},
{
"topping": "pepperoni",
"base": "sour dough"
}
]
}
如果我运行此查询:
GET pizzas/_search
{
"query": {
"nested": {
"path": "types",
"query": {
"bool": {
"filter": {
"term": {
"types.topping": "bacon"
}
}
}
}
}
}
}
我明白了:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0,
"hits": [
{
"_index": "pizzas",
"_type": "pizza",
"_id": "1",
"_score": 0,
"_source": {
"name": "meat",
"types": [
{
"topping": "bacon",
"base": "normal"
},
{
"topping": "bacon",
"base": "sour dough"
},
{
"topping": "pepperoni",
"base": "sour dough"
}
]
}
}
]
}
}
但我真正想要的是我的热门歌曲:
"hits": [
{
"_index": "pizzas",
"_type": "pizza",
"_id": "1",
"_score": 0,
"_source": {
"name": "meat",
"types": [
{
"topping": "bacon",
"base": "normal"
}
]
}
},
{
"_index": "pizzas",
"_type": "pizza",
"_id": "1",
"_score": 0,
"_source": {
"name": "meat",
"types": [
{
"topping": "bacon",
"base": "sour dough"
}
]
}
}
]
我想这样做,所以如果用户搜索“培根”,他们会得到一个披萨选项列表,他们可以使用哪些包括该顶部。
这甚至得到了Elasticsearch的支持吗?我可以通过编程方式分离出我的结果,但我希望它是内置的。
感谢您的时间。
答案 0 :(得分:0)
解决此问题的一种可能方法可能是使用_parent
和_child
关系并从其类型中分割出比萨饼:
PUT pizzas
{
"mappings": {
"pizza": {
"properties": {
"name": {
"type": "keyword"
},
"rating": {
"type": "integer"
}
}
},
"type": {
"_parent": {
"type": "pizza"
},
"properties": {
"types": {
"properties": {
"topping": {
"type": "keyword"
},
"base": {
"type": "keyword"
}
}
}
}
}
}
}
PUT pizzas/pizza/1
{
"name": "meat",
"rating": 5
}
PUT pizzas/type/1?parent=1
{
"topping": "bacon",
"base": "normal"
}
PUT pizzas/type/2?parent=1
{
"topping": "bacon",
"base": "sour dough"
}
PUT pizzas/type/3?parent=1
{
"topping": "pepperoni",
"base": "sour dough"
}
然后,您可以只搜索孩子,还可以查看与其相关的父母。
查询:
GET pizzas/type/_search
{
"query": {
"bool": {
"filter": {
"term": {
"topping": "bacon"
}
}
}
}
}
结果:
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 0,
"hits": [
{
"_index": "pizzas",
"_type": "type",
"_id": "1",
"_score": 0,
"_routing": "1",
"_parent": "1",
"_source": {
"topping": "bacon",
"base": "normal"
}
},
{
"_index": "pizzas",
"_type": "type",
"_id": "2",
"_score": 0,
"_routing": "1",
"_parent": "1",
"_source": {
"topping": "bacon",
"base": "sour dough"
}
}
]
}
}
在您的代码中,您可以将数据结合起来以创建所需的原始数据结构。
更改结构有两个问题:
一:如果您需要按子女(source)对父母进行排序,则可以设置普通排序。
二:如果您还需要过滤其他字段,则最终需要运行查询,例如:
GET pizzas/pizza/_search
{
"query": {
"bool": {
"filter": {
"term": {
"rating": 5
}
},
"must": {
"has_child": {
"type": "type",
"query": {
"bool": {
"filter": {
"term": {
"topping": "bacon"
}
}
}
}
}
}
}
}
}
然后针对那些需要重新连接到父级的特定子级的另一个查询。
答案 1 :(得分:0)
您可以使用"inner_hits"
在嵌套搜索中获取特定匹配的匹配:
查询:
GET pizzas/_search
{
"query": {
"nested": {
"path": "types",
"query": {
"bool": {
"filter": {
"term": {
"types.topping": "bacon"
}
}
}
},
"inner_hits": {
"size": 10
}
}
}
}
请注意,“inner_hits”将返回3个结果,除非明确告知返回不同的金额。您可以看到选项here。
似乎没有设置size
的选项,您只需将其设置为高于您将拥有的最大内部数量。
结果:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0,
"hits": [
{
"_index": "pizzas",
"_type": "pizza",
"_id": "1",
"_score": 0,
"_source": {
"name": "meat",
"types": [
{
"topping": "bacon",
"base": "normal"
},
{
"topping": "bacon",
"base": "sour dough"
},
{
"topping": "pepperoni",
"base": "sour dough"
}
]
},
"inner_hits": {
"types": {
"hits": {
"total": 2,
"max_score": 0,
"hits": [
{
"_nested": {
"field": "types",
"offset": 1
},
"_score": 0,
"_source": {
"topping": "bacon",
"base": "sour dough"
}
},
{
"_nested": {
"field": "types",
"offset": 0
},
"_score": 0,
"_source": {
"topping": "bacon",
"base": "normal"
}
}
]
}
}
}
}
]
}
}
使用您的代码,您可以将hits和inner_hits连接在一起,以便返回的唯一类型是相关的。