es match 可查 而 term 查不到 问题分析
es 匹配逻辑
根本:es 的匹配是基于token 的。检索的query和目标字段在token 层级上有交集才能检索成功。对同样的文本,使用不同的分词器,所得token 不同。es 默认的analyzer(分词器)是standard模式,即按字切分。
基本上,如果query 使用match 可以查到结果,而term 查不到,就是query 本身没有作为一个token在es 中存在。
实例分析
# 设置mapping,可指定每个字段的type、analyzer,如果不设置,es 会自动创建type
doc = {
'mappings': {
'properties': {
'name': {
'type': 'text',
"analyzer": "whitespace"
},
'age': {
'type': 'integer'
}
}
}
}
# 创建索引,同时指定mapping
es.indices.create(index='tt', body=doc)
# 录入数据
# 小 明明,对应的token [小, 明明]
xiaoming = {
"name": "小 明明",
"age": 10
}
# 李 东东,对应的token [李, 东东]
dongdong = {
"name": "李 东东",
"age": 9
}
es.index(index='tt', id='1', document=xiaoming)
es.index(index='tt', id='2', document=dongdong)
# 使用 “李 明明” 作为query 检索
ts = {
"query": {
"term": {
"name": "李 明明"
}
}
}
ts2 = {
"query": {
"match": {
"name": {
"query": "李 明明",
"analyzer": "whitespace"
}
}
}
}
ts3 = {
"query": {
"match": {
"name": {
"query": "李 明明"
}
}
}
}
res = es.search(index='tt', body=ts) # 结果为空
res2 = es.search(index='tt', body=ts2) # 小 明明 和 李 东东都能检索出来
res3 = es.search(index='tt', body=ts3) # 李 东东能检索出来
上例中,对于ts, 采用term 方式检索,term是不分词的,相当于采用keyword 分词器,因此token=[李 明明],显然,对于索引 tt,不存在这样的token,因此无法检索到信息。
对于ts2,采用match 方式检索,分词器为whitespace,token=[李,明明],因此和[小, 明明]存在交集【明明】;和[李 东东]存在交集【李】。所以两条数据都能检索出来。
对于ts3,采用match 方式检索,没有指定分词器,默认为standard,token=[李,明,明],和[李, 东东]存在交集【李】。所以李 东东能检索出来。