【问题标题】:Elastic search partial substring search弹性搜索部分子字符串搜索
【发布时间】:2021-06-28 20:38:41
【问题描述】:

我正在尝试使用以下分析器在弹性 serach 7.1 中实现部分子字符串搜索

PUT my_index-001

{
  "settings": {
    "analysis": {
      "analyzer": {
        "autocomplete": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "autocomplete"
          ]
        },
        "autocomplete_search": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase"
          ]
        }
      },
      "filter": {
        "autocomplete": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 40
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "string",
          "analyzer": "autocomplete",
          "search_analyzer": "autocomplete_search"
        }
      }
    }
  }
}

之后我尝试将一些示例数据添加到 my_index-001 并输入 doc

    PUT my_index-001/doc/1
    {
      "title": "ABBOT Series LTD 2014"
    }
 
    PUT my_index-001/doc/2
    {
      "title": "ABBOT PLO LTD 2014A"
    }
   
    PUT my_index-001/doc/3
    {
      "title": "ABBOT TXT"
    }
    PUT my_index-001/doc/4
    {
      "title": "ABBOT DMO LTD. 2016-II"
    }

用于执行部分搜索的查询:

GET my_index-001/_search
{
  "query": {
    "match": {
      "title": {
        "query": "ABB",
        "operator": "or"
      }
    }
  }
}

我期待分析器的以下输出

  1. 如果我输入 ABB,我应该得到 docid 1,2,3,4

  2. 如果我输入 ABB 2014 我应该得到 docid 1,2

  3. 如果我输入 ABBO PLO 我应该得到 doc 2

  4. 如果我输入 TXT,我应该得到 doc 3

使用上述分析器设置,我没有得到预期的结果。 如果我在弹性搜索的分析器设置中遗漏任何内容,请告诉我

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    几乎在那里,但有几个问题。

    1. 通过 Kibana 开发工具创建索引映射时,URI 和请求正文之间不能有任何空格。您在第一个代码 sn-p 中有空格,导致 ES 完全忽略请求正文!所以删除那个空格。
    2. 最大ngram差异is set to 1 by default。为了使用您的高 ngram 间隔,您需要显式增加索引级别设置max_ngram_diff
    PUT my_index-001
    {
      "settings": {
        "index": {
          "max_ngram_diff": 40   <--
        },
        ...
      }
    }
    
    1. v7 中不推荐使用类型名称。支持ngram(小写g)的nGram 标记过滤器也是如此。 string 字段类型也是如此!以下是更正后的 PUT 请求正文:
    PUT my_index-001                  <--- no whitespace after the URI!
    {
      "settings": {
        "index": {
          "max_ngram_diff": 40        <--- explicit setting
        },
        "analysis": {
          "analyzer": {
            "autocomplete": {
              "tokenizer": "whitespace",
              "filter": [
                "lowercase",
                "autocomplete"
              ]
            },
            "autocomplete_search": {
              "tokenizer": "whitespace",
              "filter": [
                "lowercase"
              ]
            }
          },
          "filter": {
            "autocomplete": {
              "type": "ngram",         <--- ngram, not nGram
              "min_gram": 2,
              "max_gram": 40
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "title": {
            "type": "text",            <--- text, not string
            "analyzer": "autocomplete",
            "search_analyzer": "autocomplete_search"
          }
        }
      }
    }
    
    1. 由于不同的映射类型 had been deprecated 支持通用的 _doc 类型,因此您需要调整插入文档的方式。幸运的是,唯一的区别是将 URI 中的 doc 更改为 _doc
    PUT my_index-001/_doc/1
    { "title": "ABBOT Series LTD 2014" }
     
    PUT my_index-001/_doc/2
    { "title": "ABBOT PLO LTD 2014A" }
       
    PUT my_index-001/_doc/3
    { "title": "ABBOT TXT" } 
    
    PUT my_index-001/_doc/4
    { "title": "ABBOT DMO LTD. 2016-II" }
    
    1. 最后,您的查询完全没问题,应该按照您期望的方式运行。唯一要更改的是在查询两个或多个子字符串时将operator 更改为and,即:
    GET my_index-001/_search
    {
      "query": {
        "match": {
          "title": {
            "query": "ABB 2014",
            "operator": "and"
          }
        }
      }
    }
    

    除此之外,您的所有四个测试场景都应该返回您所期望的结果。

    【讨论】:

    • 谢谢,效果很好。映射部分中这两个标签的区别是什么:“analyzer”:“autocomplete”,“search_analyzer”:“autocomplete_search”。虽然我最初有脚本,但我无法完全理解它的用法
    • 不客气。这两者的区别在here解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多