elasticsearch,Json,elasticsearch" /> elasticsearch,Json,elasticsearch" />

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": {}
                        }
                    }
                ]
            }
        }
    }