elasticsearch的keyword与text的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了elasticsearch的keyword与text的区别相关的知识,希望对你有一定的参考价值。

参考技术A 在es 2.*版本里面是没有这两个字段,只有string字段。

5.*之后,把string字段设置为了过时字段,引入text,keyword字段

这两个字段都可以存储字符串使用,但建立索引和搜索的时候是不太一样的

keyword:存储数据时候,不会分词建立索引

text:存储数据时候,会自动分词,并生成索引(这是很智能的,但在有些字段里面是没用的,所以对于有些字段使用text则浪费了空间)。

"zuMaker":
"type":"keyword","index":"false",
"zuName":
"type":"text","index":"true","boost":"5","analyzer":"ik_max_word","search_analyzer":"ik_max_word"

///////****//////
1.text类型和keyword类型

一切文本类型的字符串可以定义成 “text”或“keyword”两种类型。区别在于,text类型会使用默认分词器分词,当然你也可以为他指定特定的分词器。如果定义成keyword类型,那么默认就不会对其进行分词。

es对字符串类型的mappong设定,会将其定义成text,同时为他定义一个叫做keyword的子字段。keyword只是他的名字,你也可以定义成kw。这个字段的类型是keyword(这是一个类型的关键字)

多字段类型情况下,你可以查询 title,也可以查询title.keyword查询类型为keyword的子字段

Elasticsearch教程8Mapping字段类型之keyword

(1378条消息) Elasticsearch教程(19) 详解mapping之keyword_亚瑟弹琴的博客-CSDN博客_elasticsearch keywordhttps://blog.csdn.net/winterking3/article/details/108254346

一、前言

ES的keyword类型家族有3种:

  • keyword,用于结构化内容,如ID、邮箱、邮编、手机号、主机名、状态码或标记
  • constant_keyword,某个字段为constant_keyword类型,则该index中,所有文档的该字段的值必须一致
  • wildcard,存非机构化数据,且值的内容大,相似性低的数据,如HTTP请求体,Log日志这些让人阅读性差的数据。

其中第1个keyword类型是最常用的类型,后面2个类型出现的比较晚,使用的场景也比较少。

二、keyword

2.1 keyword适用场景

keyword类型通常存储结构化数据,对keyword类型不能进行match查询,适合用keyword的例子:

场景
订单状态1:未付款;2:已付款;3:申请退款;4:已退款
HTTP状态码200,400,500,404
ID/手机号/邮箱/性别对手机号没必要分词,也不需要数学计算,所以也不能设为数字类型
用户画像标签学生,IT男,腐女,宝妈
  • ES把keyword类型的值作为一整体存在倒排索引中,不进行分词。
  • keyword适合存结构化数据,如性别、手机号、数据状态、标签HttpCode(404,200,500)等。
  • 字段常用来精确查询、过滤、排序、聚合时,应设为keyword,而不是数值型。
  • 如果某个字段你经常用来做range查询, 你还是设置为数值型(integer,long),ES对数字的range有优化。
  • 还可以把字段设为multi-field,这样又有keyword类型又有数值类型,方便多种方式的使用。
  • 最长支持32766个UTF-8类型的字符,但放入倒排索引时,只截取前一段字符串,长度由ignore_above参数决定,默认"ignore_above" : 256。

2.2 keyword实验

(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": "冬"
    
  

2.3 手动设置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类型

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类型

当你要在某个非结构化数据上进行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"
      
    
  

以上是关于elasticsearch的keyword与text的区别的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch学习笔记filter与query

Elasticsearch教程8Mapping字段类型之keyword

Elasticsearch:没有在字段 [hostname] 上声明的类型 [keyword] 的处理程序

ElasticSearchES5新特性-keyword-text类型-查询区别

Elasticsearch中Text和Keyword类型的区别

Elasticsearch:constant keyword 数据类型