文章目录
- 一、Term query简介
- 二、Term query和Match query对比
- 1. 数据准备
- 2. 使用Match query查询
- 3. 使用Term query查询
- 三、分词器修改字段值的场景
- 1. 删除大多数标点符号
- 2. 英文大写转小写
- 3. 超过max_token_length部分单独拆分
一、Term query简介
使用Term query
可以根据精确值查找相关文档数据,不过Term query
查询与Match query
查询还是有区别的,有时候你会发现用Match query
可以查到,换成Term query
却不行,本文整理一些使用Term query
容易出错的点供参考。
如果你查看Term query
的官方文档,你就会发现,官网首先对Term query
做了3项明确说明。
- 避免是对
text
属性的字段使用Term query
查询。 Elasticsearch
会因为分词器的原因改变字段的值,所以如果想要精确匹配text
类型的字段将会很难。- 如果查询
text
类型的字段,建议使用Match query
。
二、Term query和Match query对比
1. 数据准备
建立一个索引,其中name
是keyword
类型,full_name
是text
类型。
PUT /test-index
{
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "keyword"
},
"full_name": {
"type": "text"
}
}
}
}
}
插入一条数据
PUT /test-index/_doc/1
{
"name":"zhang",
"full_name":"zhang san"
}
2. 使用Match query查询
查询name
字段
GET /test-index/_search
{
"query": {
"match": {
"name": "zhang"
}
}
}
可以查询到结果
查询full_name
字段
GET /test-index/_search
{
"query": {
"match": {
"full_name": "zhang san"
}
}
}
同样也可以查询到结果
3. 使用Term query查询
查询name
字段
GET /test-index/_search
{
"query": {
"term": {
"name": "zhang"
}
}
}
可以查询到结果
查询full_name
字段
GET /test-index/_search
{
"query": {
"term": {
"full_name": "zhang san"
}
}
}
没有查到结果
但是如果你按空格拆开来查询,比如只查询zhang
或者san
,是可以查询到结果的(Match query拆分后也可以查询到结果
)
GET /test-index/_search
{
"query": {
"term": {
"full_name": "zhang"
}
}
}
好了,到此就解释了为什么官网要做那三项说明,简单来说就是当使用Term query
查询时,如果是text
类型,会按照分词后的结果来进行匹配,而分词的规则,如果你掌握不好,那么查询时就很容易出错了。
我们也可以验证一下在standard
分词器下,zhang san
的分词结果。
POST _analyze
{
"analyzer": "standard",
"text": "zhang san"
}
可以看到,zhang san
确实被拆分为了zhang
和san
两部分。
所以使用Term query
查询时,如果直接查询zhang san
是查询不到结果的。
三、分词器修改字段值的场景
我们知道Elasticsearch
的有多种分词器,你也可以自定义分词器,所以实际上在不同的分词器下,zhang san
可能有不同的拆分方法,就像前面说的,分词的规则如果你掌握不好,就会导致查询的结果和你设想中的结果不匹配,下面,我们可以来看看默认的分词器standard analyzer
,会有哪些改变字段值的场景?
1. 删除大多数标点符号
POST _analyze
{
"analyzer": "standard",
"text": "hello! zhang san"
}
可以对比下如果是whitespace
分词器则可以识别出标点符号
POST _analyze
{
"analyzer": "whitespace",
"text": "hello! zhang san"
}
可以看到hello!
并没有被拆分开。
2. 英文大写转小写
这是一个很容易掉坑的地方。
POST _analyze
{
"analyzer": "standard",
"text": "Hello Zhang San"
}
经过standard
分词器后,大写的英文字母都被转换成了小写,所以,此时如果你还是按照Hello
来查询的话,是不会查询到结果的,这点要特别注意。
3. 超过max_token_length部分单独拆分
max_token_length
:最大令牌长度。如果超过此长度,则会被拆分开。默认值为 :255
自定义一个分词器,并设置max_token_length
长度为5。
PUT test-analyzer
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "standard",
"max_token_length": 5
}
}
}
}
}
看一下分词效果
POST test-analyzer/_analyze
{
"analyzer": "my_analyzer",
"text": "Hello, Elasticsearch"
}
可以看到,拆分后的每一项长度最多不会超过5。