Json FreeText搜索用例中的嵌套内部点击
我在一个卖车的网站上建立了一个标准的免费文本搜索 在“搜索”框中,用户可以输入一个搜索词,该词将传递到查询,用于匹配嵌套和非嵌套属性 我使用Json FreeText搜索用例中的嵌套内部点击,json,
elasticsearch,Json,
elasticsearch,我在一个卖车的网站上建立了一个标准的免费文本搜索 在“搜索”框中,用户可以输入一个搜索词,该词将传递到查询,用于匹配嵌套和非嵌套属性 我使用internal\u hits来限制查询返回的变体数量(在此示例中,variants不是从\u source中删除的) 当匹配嵌套属性color时,internal\u hits集合包含预期的正确变量 但是,当匹配非嵌套属性title时,内部\u hits集合为空。我明白为什么它是空的 你能建议一种更好的查询结构吗 另一个选择是始终只返回至少一个变量-但是如
internal\u hits
来限制查询返回的变体数量(在此示例中,variants
不是从\u source
中删除的)
当匹配嵌套属性color
时,internal\u hits
集合包含预期的正确变量
但是,当匹配非嵌套属性title
时,内部\u 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": {}
}
}
]
}
}
}
品牌查询结果:-(
您已经知道了,但是
internal\u hits
返回一个空数组,因为嵌套查询中没有匹配的嵌套文档
一个简单的解决方案是更改查询,使嵌套查询始终匹配。这可以通过将嵌套查询包装为bool
查询并添加match\u all
查询来完成
如果将match_all
查询的boost
设置为0,则它不会对分数产生影响。因此,如果嵌套文档匹配,它将是第一个
现在,内部命中不会为空,但还有第二个问题,所有文档都将匹配
- 将a设置为非常小的值(例如0.00000001)以丢弃分数为0的文档
- 复制原始嵌套查询,并在2处使用
最小值
{
“查询”:{
“布尔”:{
//确保前2个查询中至少有1个匹配
//第三个查询将始终匹配
“最小应匹配”:2,
“应该”:[
{
“匹配”:{
“标题”:
}
},
{
“嵌套”:{
“路径”:“变体”,
“查询”:{
“匹配”:{
“变体.颜色”:
}
}
}
},
{
“嵌套”:{
“路径”:“变体”,
“查询”:{
“布尔”:{
“应该”:[
{
“匹配”:{
“变体.颜色”:
}
},
{
//禁用计分
“全部匹配”:{“boost”:0}
}
]
}
},
“内部点击”:{}
}
}
]
}
}
}
一种方法是使用script\u fields
子句
您可以用painless编写一个小脚本,执行以下操作:
变体中获得的列表存储在变量中
color
blue返回地图。(如果没有,则返回空地图。)
这将为每个搜索结果创建一个附加字段,其中仅包含颜色为蓝色的变体
如果这是只有你才会做的事情,你可以采取这种方法,也许一年中在高峰时间之外会做几次。如果你的用例是经常使用的,并且需要很多用户来执行,我会改变映射,返回整个
变体,或者选择其他解决方案。这是一个免费的文本搜索和文档数量nts不是微不足道的-所以脚本不是一个选项。感谢您的回答-很好-这是问题的一个可能解决方案
"hits" : [
{
"_source" : {
"title" : "VW Golf",
"variants" : [
{
"color" : "red",
"forsale" : true
},
{
"color" : "blue",
"forsale" : false
}
]
},
"inner_hits" : {
"variants" : {
"hits" : {
"total" : 0,
"hits" : [ ]
}
}
}
}
{
"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": {}
}
}
]
}
}
}