赞
踩
ES的keyword
类型家族有3种:
keyword
,用于结构化内容,如ID、邮箱、邮编、手机号、主机名、状态码或标记constant_keyword
,某个字段为constant_keyword
类型,则该index中,所有文档的该字段的值必须一致wildcard
,存非机构化数据,且值的内容大,相似性低的数据,如HTTP请求体,Log日志这些让人阅读性差的数据。其中第1个keyword
类型是最常用的类型,后面2个类型出现的比较晚,使用的场景也比较少。
keyword
类型通常存储结构化数据,对keyword
类型不能进行match
查询,适合用keyword
的例子:
场景 | 值 |
---|---|
订单状态 | 1:未付款;2:已付款;3:申请退款;4:已退款 |
HTTP状态码 | 200,400,500,404 |
ID/手机号/邮箱/性别 | 对手机号没必要分词,也不需要数学计算,所以也不能设为数字类型 |
用户画像标签 | 学生,IT男,腐女,宝妈 |
keyword
类型的值作为一整体存在倒排索引中,不进行分词。keyword
适合存结构化数据,如性别、手机号、数据状态、标签HttpCode(404,200,500)等。keyword
,而不是数值型。integer
,long
),ES对数字的range有优化。keyword
类型又有数值类型,方便多种方式的使用。ignore_above
参数决定,默认"ignore_above" : 256
。(1)创建一个文档
PUT /pigg_user/_doc/1
{
"name": "冬哥",
"age": 32
}
(2)查询name="冬哥"的数据,用term
在name
字段上查询,是查询不到文档的
这条语句是查询不到的
GET /pigg_user/_search
{
"query": {
"term": {
"name": "冬哥"
}
}
}
(3)查看文档的mapping
要想探知没有搜到的原因,得先看排查文档的mapping,发现name是text类型
,其下面有一个keyword子类型
。
GET /pigg_user/_mapping #返回如下 { "pigg_user" : { "mappings" : { "properties" : { "age" : { "type" : "long" }, "name" : { "type" : "text", "fields" : { "keyword" : { #这行的keyword是字段名,全称是name.keyword "type" : "keyword", #这行的keyword是指类型 "ignore_above" : 256 #这里的ignore_above下面会讲 } } } } } } }
(4)分析原因
如果不设置mapping,ES默认把字符串设为text类型
,并包含一个keyword子类型
。
name是text类型
,“冬哥”这个词已经被拆成“冬”和“哥”这2个词。
所以上面用term来匹配“冬哥”时,查询不到数据。
简单理解:
“name”
这个字段按照“冬”和“哥”2个词存的,根据“冬”或者“哥”都能term查询到文档。“name.keyword”
这个字段存储的是“冬哥”这完整字符串。#根据name匹配“冬”,可以查询到文档 GET /pigg_user/_search { "query": { "term": { "name": "冬" } } } #根据name.keyword匹配"冬哥",可以查询到文档 GET /pigg_user/_search { "query": { "term": { "name.keyword": "冬哥" } } } #根据name.keyword匹配"冬",查询不到文档 GET /pigg_user/_search { "query": { "term": { "name.keyword": "冬" } } }
#先删除之前创建的index DELETE pigg_user #设置name为keyword,age为short。 PUT pigg_user { "mappings": { "properties": { "name": { "type": "keyword" }, "age": { "type": "short" } } } } #新增一个文档 PUT /pigg_user/_doc/1 { "name": "冬哥", "age": 32 } #根据name精确匹配,可以查到数据 GET /pigg_user/_search { "query": { "term": { "name": "冬哥" } } }
constant_keyword
是 keyword
字段的特例,用于索引中所有文档具有相同值的情况。
PUT logs-debug { "mappings": { "properties": { "@timestamp": { "type": "date" }, "message": { "type": "text" }, "level": { "type": "constant_keyword", #指明level这个字段是constant_keyword类型 "value": "debug" #且所有文档的level字段的值都是debug } } } }
constant_keyword
支持与 keyword
字段相同的查询和聚合,而且constant_keyword
的效率更高,因为ES利用所有文档的的某个constant_keyword
字段的值必须相同的这一事实,进行了针对性优化。
允许提交没有字段值
或值等于映射中配置的值
的文档。 以下两个索引请求是等效的:
POST logs-debug/_doc
{
"date": "2019-12-12",
"message": "Starting up Elasticsearch",
"level": "debug"
}
POST logs-debug/_doc
{
"date": "2019-12-12",
"message": "Starting up Elasticsearch"
}
如果把level
设置成非debug
的值,比如error
,则会返回错误
POST logs-debug/_doc
{
"date": "2019-12-12",
"message": "Starting up Elasticsearch",
"level": "error"
}
返回如下错误提示:
"caused_by" : {
"type" : "illegal_argument_exception",
"reason" : "[constant_keyword] field [level] only accepts values that are equal to the value defined in the mappings [debug], but got [error]"
}
constant_keyword
类型使用的场景确实非常少见,所以用的很少。
当你要在某个非结构化数据上进行wildcard
或regexp
查询的时候,wildcard类型
就比较合适了。
machine-generated
),它们的可阅读比较低,不适合我们人阅读,比如日志message或者HTTP的请求体。PUT my-index-000001 { "mappings": { "properties": { "my_wildcard": { "type": "wildcard" } } } } PUT my-index-000001/_doc/1 { "my_wildcard" : "This string can be quite lengthy" } GET my-index-000001/_search { "query": { "wildcard": { "my_wildcard": { "value": "*quite*lengthy" } } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。