Elasticsearch中match与query_string差异及match工作原理问询
理解Elasticsearch中match查询的工作机制
你的这两个场景刚好戳中了match查询最核心的两个特性:依赖分词器处理查询词,以及默认的匹配逻辑。让我逐个给你拆解清楚:
一、为什么match查"ka"没结果,query_string的ka却能命中?
match查询的工作流程是固定的:
- 首先会把你输入的查询词(这里是"ka"),用和目标字段(
name)相同的分词器进行分词处理。 - 然后拿着分词后的结果,去Elasticsearch的倒排索引里找完全匹配的分词项。
而你的name字段里的"katyperry"、"KathleenLights"这类值,被分词器处理后是作为完整的单个分词存在的(比如默认的标准分词器不会把英文单词拆成前缀)。当你用match查"ka"时,分词后的查询词就是"ka",但倒排索引里根本没有"ka"这个分词项——只有"katyperry"、"kathleenlights"这类完整分词,所以自然匹配不到任何结果。
而你用的query_string加*ka*属于通配符查询,逻辑完全不同:
- 通配符查询不会对查询词做分词处理,而是直接去倒排索引里找包含"ka"子串的所有分词项。比如"katyperry"这个分词里包含"ka",所以会被命中,这就是为什么能返回1000+条结果。
二、为什么match查邮箱会返回所有含"gmail.com"的结果?
这个问题和分词器以及match查询的默认规则有关:
- 当你查询
"email":"testname@gmail.com"时,match查询会先把这个邮箱地址用email字段的分词器处理。如果是默认的标准分词器,它会把testname@gmail.com拆分成三个分词:testname、gmail、com。 - match查询的默认匹配逻辑是OR——也就是说,只要文档的
email字段包含这三个分词中的任意一个,就会被匹配到。
所以你的查询实际上等价于:找email字段包含testname OR gmail OR com的文档。那些包含"gmail.com"的邮箱,显然会被分词出gmail和com,自然就会被命中返回。
如果想要精确匹配整个邮箱地址,你有几个实用的选择:
- 用
match_phrase查询:{"match_phrase": {"email": "testname@gmail.com"}},它会要求分词后的项按顺序完整匹配。 - 把
email字段设置为keyword类型(或添加一个keyword子字段),然后用term查询精确匹配整个字符串。 - 修改match查询的operator为AND:
{"match": {"email": {"query": "testname@gmail.com", "operator": "and"}}},这样需要三个分词都存在才会匹配。
内容的提问来源于stack exchange,提问作者Xin
相关产品推荐
相关产品推荐

