我在销售汽车的网站上建立了标准的免费文本搜索。
在搜索框中,用户可以输入传递给查询的搜索词,该词用于匹配嵌套和非嵌套属性。
我正在使用inner_hits
来限制查询返回的变体数量(在此示例中,variants
并未从_source
中删除)
在嵌套属性color
上进行匹配时,inner_hits
集合包含预期的正确变体。
但是,当对非嵌套属性title
进行匹配时,inner_hits
集合为空。我知道为什么它是空的。
您能建议一种更好的查询结构吗?
另一种选择是始终仅返回至少一个变体-但是如何实现?
映射
PUT test
{
"mappings": {
"car": {
"properties": {
"variants": {
"type": "nested"
}
}
}
}
}
插入数据
PUT test/car/1
{
"title": "VW Golf",
"variants": [
{
"color": "red",
"forsale": true
},
{
"color": "blue",
"forsale": false
}
]
}
按颜色查询
GET test/_search
{
"query": {
"nested": {
"path": "variants",
"query": {
"match": {
"variants.color": "blue"
}
},
"inner_hits": {}
}
}
}
颜色查询:按预期工作!
"hits" : [
{
"_source" : {
"title" : "VW Golf",
"variants" : [
{
"color" : "red",
"forsale" : true
},
{
"color" : "blue",
"forsale" : false
}
]
},
"inner_hits" : {
"variants" : {
"hits" : {
"total" : 1,
"hits" : [
{
"_nested" : {
"field" : "variants",
"offset" : 1
},
"_source" : {
"color" : "blue",
"forsale" : false
}
}
]
}
}
}
}
]
按品牌查询
GET test/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": "golf"
}
},
{
"nested": {
"path": "variants",
"query": {
"match": {
"variants.color": "golf"
}
},
"inner_hits": {}
}
}
]
}
}
}
品牌查询结果:-(
"hits" : [
{
"_source" : {
"title" : "VW Golf",
"variants" : [
{
"color" : "red",
"forsale" : true
},
{
"color" : "blue",
"forsale" : false
}
]
},
"inner_hits" : {
"variants" : {
"hits" : {
"total" : 0,
"hits" : [ ]
}
}
}
}
答案 0 :(得分:1)
您已经知道它,但是inner_hits
返回一个空数组,因为在嵌套查询中没有匹配的嵌套文档。
一个简单的解决方案是更改查询,以使嵌套查询始终匹配。这可以通过将嵌套查询包装到bool
查询中并添加match_all
查询来完成。
如果将boost
查询的match_all
设置为0,它将不会对得分有所贡献。因此,如果嵌套文档匹配,它将是第一个。
现在,内部匹配项将不会为空,但是还有另一个问题,所有文档都将匹配。您可以:
min_score
设置为非常小的值(例如0.00000001)以丢弃得分为0的文档minimum_should_match
。{
"query": {
"bool": {
// Ensure that at least 1 of the first 2 queries will match
// The third query will always match
"minimum_should_match": 2,
"should": [
{
"match": {
"title": <SEARCH_TERM>
}
},
{
"nested": {
"path": "variants",
"query": {
"match": {
"variants.color": <SEARCH_TERM>
}
}
}
},
{
"nested": {
"path": "variants",
"query": {
"bool": {
"should": [
{
"match": {
"variants.color": <SEARCH_TERM>
}
},
{
// Disable scoring
"match_all": { "boost": 0 }
}
]
}
},
"inner_hits": {}
}
}
]
}
}
}
答案 1 :(得分:1)
一种实现方法是使用script_fields
子句。
您将轻松编写一个小脚本,该脚本将执行以下操作:
variants
获得的 List 存储在变量中color
蓝色,您将返回地图。 (如果没有结果为true,则返回一个空
地图)。这将为每个搜索结果创建一个附加字段,仅包含color
为蓝色的那些变体。一个重要的缺点是这是非常繁重的操作,尤其是在您有很多记录的情况下。
如果您只能做这种事情,可以采取这种方法,也许一年高峰时段以外可能会这样做一次。如果您的用例是经常使用的并且要由许多用户执行,那么我将更改映射,整体返回variants
或选择其他解决方案。