Elasticsearch 6.2:带空格与无空格的查询字符串问题
解决Elasticsearch 6.2中"spiderman"与"Spider man"的查询匹配问题
这个问题我之前处理过,核心原因是你的movie_title字段分词逻辑和查询词形没对齐——默认的标准分词器会把"Spider man"拆成["spider", "man"]两个独立词,而"Spiderman"会被处理成单个词["spiderman"]。当你用query_string搜索"spiderman"时,因为default_operator设为AND,ES只会去找包含完整"spiderman"词的文档,自然匹配不到拆分的那条。
下面给你几个可行的解决方案,按精准度和推荐程度排序:
方案一:添加同义词过滤器(最推荐)
通过自定义分析器,把"spiderman"和"spider man"设为同义词,这样无论索引还是查询时,两种写法都会被转换成相同的词集合,从根源解决匹配问题。
- 先删除旧索引(如果数据可以重新导入的话),然后创建带同义词配置的新索引:
PUT /movies { "settings": { "analysis": { "filter": { "movie_synonyms": { "type": "synonym", "synonyms": [ "spiderman, spider man" ] } }, "analyzer": { "movie_title_analyzer": { "tokenizer": "standard", "filter": [ "lowercase", "movie_synonyms" ] } } } }, "mappings": { "_doc": { "properties": { "movie_title": { "type": "text", "analyzer": "movie_title_analyzer", "search_analyzer": "movie_title_analyzer" } } } } }
- 重新导入你的两条文档,此时:
- "Spider man"会被分词为
["spider", "man", "spiderman"] - "Spiderman"会被分词为
["spiderman", "spider", "man"]
- "Spider man"会被分词为
- 再用你原来的查询语句搜索"spiderman",就能匹配到两条文档了。
方案二:使用模糊查询(无需改索引,适合临时场景)
如果不想重新构建索引,可以用模糊查询允许一定的编辑距离,让"spiderman"能匹配到"spider man"(两者编辑距离为1,刚好在默认允许范围内):
{ "query_string" : { "default_field": "movie_title", "default_operator": "AND", "analyze_wildcard": true, "query": "spiderman~" } }
注意:这种方法可能会匹配到其他类似拼写的词(比如"spidermn"),精准度不如同义词方案,适合临时应急。
方案三:使用N-Gram分析器(适合通用拼写变体场景)
如果你的场景不止这一个词需要处理(比如还有"batman"和"bat man"这类情况),可以用N-Gram把词拆分为连续的字符片段,让不同写法的词有重叠的片段从而匹配:
- 创建带N-Gram分析器的索引:
PUT /movies { "settings": { "analysis": { "analyzer": { "ngram_analyzer": { "tokenizer": "ngram_tokenizer", "filter": ["lowercase"] } }, "tokenizer": { "ngram_tokenizer": { "type": "ngram", "min_gram": 2, "max_gram": 3 } } } }, "mappings": { "_doc": { "properties": { "movie_title": { "type": "text", "analyzer": "ngram_analyzer", "search_analyzer": "standard" } } } } }
这种方式会让"spiderman"和"Spider man"的分词结果有大量重叠片段,搜索时就能互相匹配,但会增加索引体积,可能引入一些无关匹配,需要根据你的场景权衡。
内容的提问来源于stack exchange,提问作者Kévin E.
相关产品推荐
相关产品推荐

