在not_analyzed字段上进行Elasticsearch通配符搜索

发布于 2021-02-01 12:03:07

我有一个类似以下设置和映射的索引;

{
  "settings":{
     "index":{
        "analysis":{
           "analyzer":{
              "analyzer_keyword":{
                 "tokenizer":"keyword",
                 "filter":"lowercase"
              }
           }
        }
     }
  },
  "mappings":{
     "product":{
        "properties":{
           "name":{
              "analyzer":"analyzer_keyword",
              "type":"string",
              "index": "not_analyzed"
           }
        }
     }
  }
}

我正在努力实现name现场通配符搜索的实现。我的示例数据如下:

[
{"name": "SVF-123"},
{"name": "SVF-234"}
]

当我执行以下查询时;

http://localhost:9200/my_index/product/_search -d '
{
    "query": {
        "filtered" : {
            "query" : {
                "query_string" : {
                    "query": "*SVF-1*"
                }
            }
        }

    }
}'

它返回SVF-123SVF-234。我认为,它仍然标记数据。它只能返回SVF-123

您能帮上忙吗?

提前致谢

关注者
0
被浏览
121
1 个回答
  • 面试哥
    面试哥 2021-02-01
    为面试而生,有面试问题,就找面试哥。

    我的解决方案历险记

    如您在我的问题中所见,我已经开始审理案件。每当我更改了一部分设置后,一部分便开始工作,而另一部分则停止工作。让我给出我的解决方案历史记录:

    1.) 我已将数据索引为默认值。这意味着,我的数据是analyzed默认的。这将在我这方面引起问题。例如;

    当用户开始搜索诸如 SVF-1 的关键字时,系统将运行以下查询:

    {
        "query": {
            "filtered" : {
                "query" : {
                    "query_string" : {
                        "analyze_wildcard": true,
                        "query": "*SVF-1*"
                    }
                }
            }
    
        }
    }
    

    和结果;

    SVF-123
    SVF-234
    

    这是正常现象,因为name我的文档字段是analyzed。这将查询分为记号SVF1,并SVF与我的文档匹配,尽管1不匹配。我已经跳过了。我为我的字段创建了一个映射not_analyzed

    {
      "mappings":{
         "product":{
            "properties":{
               "name":{
                  "type":"string",
                  "index": "not_analyzed"
               },
               "site":{
                  "type":"string",
                  "index": "not_analyzed"
               } 
            }
         }
      }
    }
    

    但我的问题仍然存在。

    2.)
    经过大量研究,我想尝试另一种方法。决定使用通配符查询。我的查询是

    {
        "query": {
            "wildcard" : {
                "name" : {
                    "value" : *SVF-1*"
                 }
              }
          },
                "filter":{
                        "term": {"site":"pro_en_GB"}
                }
        }
    }
    

    该查询有效,但是这里有一个问题。我的字段不再进行分析,我正在进行通配符查询。区分大小写是这里的问题。如果我像 svf-1
    一样搜索,它什么也不会返回。因为,用户可以输入小写版本的查询。

    3.) 我将文档结构更改为;

    {
      "mappings":{
         "product":{
            "properties":{
               "name":{
                  "type":"string",
                  "index": "not_analyzed"
               },
               "nameLowerCase":{
                  "type":"string",
                  "index": "not_analyzed"
               }
               "site":{
                  "type":"string",
                  "index": "not_analyzed"
               } 
            }
         }
      }
    }
    

    我还增加了一个name名为的字段nameLowerCase。索引文档时,我将文档设置为:

    {
        name: "SVF-123",
        nameLowerCase: "svf-123",
        site: "pro_en_GB"
    }
    

    在这里,我将查询关键字转换为小写并在新nameLowerCase索引上进行搜索操作。并显示name字段。

    我查询的最终版本是;

    {
        "query": {
            "wildcard" : {
                "nameLowerCase" : {
                    "value" : "*svf-1*"
                 }
              }
          },
                "filter":{
                        "term": {"site":"pro_en_GB"}
                }
        }
    }
    

    现在可以了。还有一种使用multi_field解决此问题的方法。我的查询包含破折号(-),并且遇到了一些问题。

    非常感谢@Alex Brasetvik的详细解释和努力



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看