Elasticsearch自定义分词器搜索无结果问题求助
我来帮你分析这个问题的根本原因,以及给出彻底的解决办法:
根本原因
你遇到的核心问题是Elasticsearch不允许修改已有字段的分析器,具体细节如下:
- 你最初创建
documents索引时没有指定自定义分词器,当第一次写入数据时,Elasticsearch会自动动态创建question和question_group字段,并使用默认的standard分析器处理这些字段的内容。 - 之后你关闭索引尝试更新settings和mappings,想把这两个字段的分析器改成
custom_analyzer——但这是行不通的!Elasticsearch为了保证索引数据的一致性,禁止修改已存在字段的分析器(因为字段的分词逻辑一旦确定,修改后会导致旧数据的分词结果和新查询的分词结果不匹配)。所以你的修改操作实际上没有生效,这两个字段还是在用默认的standard分析器。 - 至于你重新创建
documents5索引后仍然有问题,大概率是因为你重复了同样的错误:先创建空索引,再试图修改字段的分析器,而不是在创建索引时就一次性配置好正确的settings和mappings。
彻底解决方法
要解决这个问题,你需要从创建索引的源头就配置好自定义分词器,再重新导入数据,具体步骤如下:
1. 正确创建带自定义分词器的新索引
直接在创建索引时就指定好settings和mappings,确保字段从一开始就使用你的custom_analyzer:
PUT /documents_new { "settings": { "analysis": { "analyzer": { "custom_analyzer": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "word_delimiter_graph"] } } } }, "mappings": { "properties": { "question": {"type": "text", "analyzer": "custom_analyzer"}, "question_group": {"type": "text", "analyzer": "custom_analyzer"} } } }
2. 确认字段的分析器配置生效
你可以用下面的请求验证question字段是否真的使用了自定义分词器:
GET /documents_new/_mapping/field/question
返回的结果里应该能看到"analyzer": "custom_analyzer",这就说明配置生效了。
3. 重新索引数据
把旧索引里的数据导入到新索引中,这样数据会用新的分词器重新处理:
POST /_reindex { "source": { "index": "documents" }, "dest": { "index": "documents_new" } }
4. 测试搜索功能
现在再尝试搜索fire或者fire detected:
POST /documents_new/_search { "query": { "multi_match": { "query": "fire detected", "fields": ["question^2", "question_group"] } } }
这次应该能成功匹配到包含FIRE_DETECTED的文档了——因为custom_analyzer会把FIRE_DETECTED拆成fire和detected两个token,而你的查询字符串也会被同一个分词器拆成这两个token,两者就能对应上了。
可选优化:调整分词器的保留原始token行为
默认情况下,word_delimiter_graph会保留原始的fire_detected token(也就是同时存储拆分后的和原始的token)。如果你不需要保留原始的下划线形式token,可以修改分词器的配置,添加preserve_original: false:
PUT /documents_new { "settings": { "analysis": { "analyzer": { "custom_analyzer": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", { "type": "word_delimiter_graph", "preserve_original": false }] } } } }, "mappings": { "properties": { "question": {"type": "text", "analyzer": "custom_analyzer"}, "question_group": {"type": "text", "analyzer": "custom_analyzer"} } } }
这样索引里只会存储拆分后的fire和detected,不会保留fire_detected。
内容的提问来源于stack exchange,提问作者Tran Dinh Huy
相关产品推荐
相关产品推荐

