【问题标题】:Multiple tokenizers inside one Custom Analyser in ElasticsearchElasticsearch 中的一个自定义分析器中的多个标记器
【发布时间】:2019-03-04 02:40:00
【问题描述】:

我正在使用具有 ngram 标记器的自定义 NGRAM 分析器。我也使用了小写过滤器。该查询适用于没有字符的搜索。但是当我搜索某些符号时,它失败了。由于我使用了小写分词器,因此 Elasticsearch 不会分析符号。我知道空格标记器可以帮助我解决问题。如何在一个分析器中使用两个分词器?下面是映射:

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer":"my_tokenizer",
          "filter":"lowercase"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 3,
          "max_gram": 3,
          "token_chars": [
            "letter", 
            "digit"
          ]
        }
      }
    }
  },
    "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "my_analyzer"
        }
      }
    }
  }

}

有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    如果你想使用 2 个分词器,你应该有 2 个分析器。 像这样:

    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer":"my_tokenizer",
              "filter":"lowercase"
            },
            "my_analyzer_2": {
              "tokenizer":"whitespace",
              "filter":"lowercase"
            }
          },
          "tokenizer": {
            "my_tokenizer": {
              "type": "ngram",
              "min_gram": 3,
              "max_gram": 3,
              "token_chars": [
                "letter", 
                "digit"
              ]
            }
          }
        }
      },
        "mappings": {
        "_doc": {
          "properties": {
            "title": {
              "type": "text",
              "analyzer": "my_analyzer"
            }
          }
        }
      }
    
    }
    

    一般来说,您还应该注意分析器在 Mapping 中的位置。 有时需要在 serach_time 和 index_time 中都有分析器。

    "mappings":{
        "_doc":{
          "properties":{
            "title":{
              "type":"text",
              "analyzer":"my_analyzer",
              "search_analyzer":"my_analyzer"
            }
          }
        }
      }
    

    【讨论】:

      【解决方案2】:

      1) 您可以尝试更新您的token_chars,如下所示:

            "token_chars":[
              "letter",
              "digit",
              "symbol",
              "punctuation"
            ]
      

      2) 如果不起作用,请尝试以下分析器:

      {
        "settings":{
          "analysis":{
            "filter":{
              "my_filter":{
                "type":"ngram",
                "min_gram":3,
                "max_gram":3,
                "token_chars":[
                  "letter",
                  "digit",
                  "symbol",
                  "punctuation"
                ]
              }
            },
            "analyzer":{
              "my_analyzer":{
                "type":"custom",
                "tokenizer":"keyword",
                "filter":[
                  "lowercase",
                  "like_filter"
                ]
              }
            }
          }
        },
        "mappings":{
          "_doc":{
            "properties":{
              "title":{
                "type":"text",
                "analyzer":"my_analyzer"
              }
            }
          }
        }
      }
      

      您需要在分析器中使用关键字标记器 (keyword tokenizer),然后使用 ngram 标记过滤器。

      【讨论】:

      • 感谢您的回复。
      【解决方案3】:

      根据 elasticsearch 的文档,

      An analyzer must have exactly one tokenizer.

      但是,您可以在设置中定义多个分析器,并且可以为每个字段配置单独的分析器。

      如果您希望使用不同的分析器来使用单个字段本身,则一种选择是根据 link 使该字段成为多字段

      PUT my_index
      {
        "mappings": {
          "_doc": {
            "properties": {
              "title": {
                "type": "text",
                "analyzer": "whitespace"
                "fields": {
                  "ngram": { 
                    "type":  "text",
                    "analyzer": "my_analyzer"
                  }
                }
              }
            }
          }
        }
      }
      

      因此,如果您按照上述方式进行配置,您的查询需要使用 titletitle.ngram 字段。

      GET my_index/_search
      {
        "query": {
          "multi_match": {
            "query": "search @#$ whatever",
            "fields": [ 
              "title",
              "title.ngram"
            ],
            "type": "most_fields" 
          }
        }
      }
      

      作为另一种选择,您可以这样做

      • 创建两个索引。
      • 第一个索引有字段title 和分析器my_analyzer
      • 第二个索引有字段title 和分析器whitespace
      • 为他们两个创建相同的alias,如下所示

      执行以下操作:

      POST _aliases
      {  
         "actions":[  
            {  
               "add":{  
                  "index":"index A",
                  "alias":"index"
               }
            },
            {  
               "add":{  
                  "index":"index B",
                  "alias":"index"
               }
            }
         ]
      }
      

      因此,当您最终编写查询时,它必须指向此别名,而该别名又将查询多个索引。

      希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 2017-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多