Elasticsearch 中一个自定义分析器内的多个分词器

M N*_*esh 5 elasticsearch

我正在使用自定义 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"
        }
      }
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

我有办法解决这个问题吗?

Kam*_*mal 5

根据elasticsearch的文档,

分析器必须恰好有一个分词器。

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

如果您希望使用不同的分析器使用单个字段本身,选项之一是按照此链接将该字段设置为多字段

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "whitespace"
          "fields": {
            "ngram": { 
              "type":  "text",
              "analyzer": "my_analyzer"
            }
          }
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

GET my_index/_search
{
  "query": {
    "multi_match": {
      "query": "search @#$ whatever",
      "fields": [ 
        "title",
        "title.ngram"
      ],
      "type": "most_fields" 
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

作为另一种选择,您可以执行以下操作

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

执行以下命令:

POST _aliases
{  
   "actions":[  
      {  
         "add":{  
            "index":"index A",
            "alias":"index"
         }
      },
      {  
         "add":{  
            "index":"index B",
            "alias":"index"
         }
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助!