当前位置: 首页 > news >正文

Elasticsearch教程(19) 详解mapping之keyword

Elasticsearch已升级,新版Elasticsearch keyword博客参考下面这篇【Elasticsearch教程8】Mapping字段类型之keyword_elasticsearch的keyword_亚瑟弹琴的博客-CSDN博客

1 前言
本文基于ES7.6,如果是之前版本,是有区别的。
ES支持的字段类型很多,但工作中常用的也就那些核心字段。 一开始学习ES时,掌握好常用的类型,不必要精通每一种,如果工作中遇到了需要用到特殊类型再去研究。
学习一门技术要先广度后深度,不能陷入”只见树木,不见森林“。
2 核心类型
2.1 关键词:keyword
keyword类型通常存储结构性数据,而不是毫无规律可言的文本信息。

2.1.1 适合用keyword的例子
场景    值
订单状态的枚举值    1:未付款;2:已付款;3:申请退款;4:已退款
HTTP状态码    200;400;500;404
手机号/邮箱/性别    对手机号没必要分词,也不需要数学计算,所以也不能设为数字类型
用户画像标签    学生,IT男,屌丝女,孕妈,社会中产
2.1.2 说明
ES把keyword类型的值当作词根存在倒排索引中,不进行分词。
keyword适合存结构化数据,比如name,age,性别,手机号,status(数据状态),tags(标签),HttpCode(404,200,500)等。
字段常用来精确查询,过滤,排序,聚合时,应设为keyword,而不是数值型。
如果某个字段你经常用来做range查询, 你还是设置为数值型(integer,long),ES对数字的range有优化。
还可以把字段设为multi-field,这样又有keyword类型又有数值类型, 方便各个方式的使用。
最长支持32766个UTF-8类型的字符,但放入倒排索引时,只截取前一段字符串,长度由ignore_above参数决定。
2.1.3 实验
(1)创建一个文档

PUT /pigg_user/_doc/1
{
  "name": "冬哥",
  "age": 32
}

(2)查询数据

GET /pigg_user/_doc/1/_source

#返回结果如下,说明插入成功:
{
  "name" : "冬哥",
  "age" : 32
}
1
2
3
4
5
6
7
(3)查询name="冬哥"的数据

GET /pigg_user/_search
{
  "query": {
    "term": {
      "name": "冬哥"
    }
  }
}

#返回结果如下,居然没有搜索到???
{
  ...省略其它信息...
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(4)查看文档的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下面会讲
            }
          }
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(5)分析原因
如果不设置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": "冬"
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2.1.4 手动设置mapping
#先删除之前创建的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": "冬哥"
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2.1.5 ignore_above是什么?
首先随意往ES插一条数据:

put my_index/_doc/1
{
  "name": "李星云"
}
1
2
3
4
查看ES自动生成的mapping,name是text类型,其下还有子类型keyword,且"ignore_above" : 256

GET /my_index/_mapping

name定义如下:
"properties" : {
  "name" : {
    "type" : "text",
    "fields" : {
      "keyword" : {
        "type" : "keyword",
        "ignore_above" : 256
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
对于keyword类型, 可设置ignore_above限定字符长度。超过 ignore_above 的字符会被存储,但不会被倒排索引。比如ignore_above=4,”abc“,”abcd“,”abcde“都能存进ES,但是不能根据”abcde“检索到数据。

【1】创建一个keyword类型的字段,ignore_above=4

PUT test_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "message": {
          "type": "keyword",
          "ignore_above": 4
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
【2】向索引插入3条数据:

PUT /test_index/_doc/1
{
  "message": "abc"
}

PUT /test_index/_doc/2
{
  "message": "abcd"
}

PUT /test_index/_doc/3
{
  "message": "abcde"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
此时ES倒排索引是:

词项    文档ID
abc    1
abcd    2
【3】根据message进行terms聚合:    
GET /test_index/_search
{
  "size": 0, 
  "aggs": {
    "term_message": {
      "terms": {
        "field": "message",
        "size": 10
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
返回结果:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "message" : "abcd"
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "message" : "abc"
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "message" : "abcde"
        }
      }
    ]
  },
  "aggregations" : {
    "term_message" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [#注意这分组里没有”abcde“
        {
          "key" : "abc",
          "doc_count" : 1
        },
        {
          "key" : "abcd",
          "doc_count" : 1
        }
      ]
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
【4】根据”abcde“进行term精确查询,结果为空

GET /test_index/_search
{
  "query": {
    "term": {
      "message": "abcde"
    }
  }
}

然后结果:
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
通过上面结果能知道”abcde“已经存入ES,也可以搜索出来,但是不存在词项”abcde“,不能根据”abcde“作为词项进行检索。
对于已存在的keyword字段,其ignore_above子属性可以修改,但只对新数据有效。
————————————————
版权声明:本文为CSDN博主「亚瑟弹琴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/winterking3/article/details/108254346

http://www.lryc.cn/news/25326.html

相关文章:

  • LeetCode算法复杂度分析(时间复杂度空间复杂度)
  • Android OpenCV(七十三):吊打高斯模糊的StackBlur Android 实践
  • 4.排序算法之一:冒泡排序
  • python自学之《21天学通Python》(16)——第19章 用Pillow库处理图片
  • 发布依赖到maven仓库
  • Laravel-admin之自定义操作日志
  • 用Python做了一个法律查询小工具,非常好用
  • 工作篇:触摸屏原理介绍
  • Ep_操作系统面试题-操作系统的分类
  • iframe或document监听滚动事件不起作用
  • 基频估计算法简介
  • linux修改DNS 系统版本Kylin V10桌面版
  • 如何使用 AWS Lambda 运行 selenium
  • 认识Cesium旋转大小变量
  • 异响加持、吐槽声不断,小鹏G9难解困局
  • 【react】react18的学习
  • Ep_操作系统面试题-什么是线程,线程和进程的区别
  • 最流行的自动化测试工具,总有一款适合你(附部分教程)
  • Shell高级——进程替换vs管道
  • 国内有哪些支持定制化的低代码平台?
  • Altair 宣布将于3月举办 Future.Industry 2023 全球虚拟大会
  • react lazyLoad学习记录
  • 29 openEuler管理网络-配置网络绑定
  • RTT 全志D1s RDC2022纪念版开发板开箱使用分享与折腾记录
  • 24日常实习万得一面面径
  • MySQL的DML和DDL操作(1)
  • Kafka系列之:Kafka生产者和消费者
  • Linux进程间通信:信号量(一)
  • Python笔记一之excel的读取
  • JavaScript Number 数字对象