1、ElasticSearch安装,新增删除索引,映射参数详解,文档增删改,分词器详解
- 一、什么是Elasticsearch
- 1.1 、ES搜索快的原因?
- 二、ES中一些名词概念
- 2.1、文档(document)
- 2.2、索引(index)
- 2.3、类型(type)
- 2.4、映射(mapping)
- 2.5、字段(field)
- 2.6、主键(ID)
- 三、ES安装
- 3.1 安装
- 3.2 安装问题排查
- 四、ES索引(index)操作
- 4.1 创建索引
- 4.2 查看索引
- 4.3 删除索引
- 五、ES映射(mappings)操作
- 5.1 动态映射
- 5.2 静态映射
- 5.3 映射数据说明
- 5.4 特殊的映射属性说明
- 5.4 新增映射字段属性
- 六、ES文档操作
- 6.1 创建文档
- 6.2 查询文档
- 6.3 修改文档
- 6.4 修改文档中的某个字段
- 6.5 删除文档
- 七、分词器(Analyzer)
- 7.1 内置分词器
- 7.2 中文分词器
- 7.2.1 安装分词器
- 7.2.2 扩展词汇(自定义词汇)
- 7.3 分词器中的一些用法
- 7.3.1 _analyze用法
- 7.3.2 默认分词器说明
- 7.3.3 查看文档中某一个字段的分词结果
一、什么是Elasticsearch
Elaticsearch简称为 ES, ES是一个开源的分布式搜索引擎,可用于实现全文搜索、日志分析、业务分析等应用。它是建立在Apache Lucene搜索引擎基础上的,提供了高效的搜索、分析和聚合功能,并支持实时数据处理和可伸缩性。
1.1 、ES搜索快的原因?
1、ES使用了倒排索引这种数据结构来快速查找文档。倒排索引是一种针对文本搜索而优化的数据结构,它将每个词与出现这个词的文档列表关联起来,这样就可以快速查找包含某些词的文档。
2、ES使用了分布式系统的优势,可以利用多台机器的计算能力来处理查询。它将索引分成若干个分片,并在多台机器上进行分布式存储,这样就可以并行处理查询,提升查询效率。
3、ES还有很多优化查询的功能,比如布尔查询、聚合查询、嵌套查询等,这些功能都可以帮助快速定位符合查询条件的文档。
二、ES中一些名词概念
2.1、文档(document)
文档是存储在Elasticsearch中的一个JSON格式的字符串。它就像在关系数据库中表的一行。每个存储在索引中的一个文档都有一个类型和一个ID,每个文档都是一个JSON对象,存储了零个或多个字段或键值对。原始的JSON文档被存储在一个叫做_source的字段中,当搜索文档的时候默认返回的就是这个字段。
2.2、索引(index)
索引是具有相同结构的文档集合。在系统上索引的名字全部为小写,通过这个索引名字可以用来执行索引、搜索、更新和删除操作。索引类似Mysql中的库。
2.3、类型(type)
类型是索引的逻辑分区。一般情况下,一种类型被定义为具有一组公共字段的文档。
注:elasticsearch7已经移除type概念,不再支持指定索引类型,默认索引类型是_doc。
2.4、映射(mapping)
类似于mysql中的表结构。创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,每一个索引都有一个映射,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)
2.5、字段(field)
字段类似关系数据库中表的字段,每一个文档包含零个或多个字段。
2.6、主键(ID)
唯一标识,如果没有提供,系统会自动生成。文档的ID必须是唯一的。
三、ES安装
本文介绍Windows环境下安装ES,官网下载地址,由于公司使用的是7.8版本,我们这就安装7.8版本的ES。
3.1 安装
1、把文件解压,进入到bin目录下,双击执行elasticsearch.bat文件,即是启动成功。如下图即是启动成功。
注意:es启动会占用两个端口,9200和9300,9300 端口为 Elasticsearch 集群间组件的通信端口,9200 端口为浏览器访问的 http协议 RESTful 端口
访问地址: http://localhost:9200, 下面中的number就表示ES版本7.8.0
3.2 安装问题排查
1、ES是使用 java 开发的,且 7.8 版本的 ES 需要 JDK 版本 1.8 及以上,这里建议用JDK1.8
2、启动ES时,双击elasticsearch.bat闪退,大概率是ES占用内存太大导致,修改ES目录的/config/jvm.options文件,如下图。
注意: 默认占用内存是1g,一般电脑是没问题的
四、ES索引(index)操作
4.1 创建索引
1、创建索引: PUT请求,http://127.0.0.1:9200/shopping,表示创建一个名为shopping的索引。
#返回数据
{
"acknowledged": true, #请求接口成功
"shards_acknowledged": true, #分片操作成功
"index": "shopping" #创建的索引名称
}
4.2 查看索引
1、查看指定索引: GET请求,http://127.0.0.1:9200/shopping
{
"shopping": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1689079823941", #索引创建时间
"number_of_shards": "1", #索引分片数量
"number_of_replicas": "1", #索引副本数量
"uuid": "033uQUgwRkufdi4QPI9cEQ",
"version": {
"created": "7080099"
},
"provided_name": "shopping"
}
}
}
}
2、查看所有索引: GET请求,http://127.0.0.1:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open shopping2 _7zn-x_WTZGCnC223lj3VQ 1 1 0 0 208b 208b
yellow open shopping 033uQUgwRkufdi4QPI9cEQ 1 1 0 0 208b 208b
4.3 删除索引
1、删除指定索引: DELETE请求,http://127.0.0.1:9200/shopping
{
"acknowledged": true #请求接口成功
}
五、ES映射(mappings)操作
5.1 动态映射
动态映射的意思是在创建索引后,不用创建映射,直接插入文档,根据插入的文档判断数据类型自动创建映射关系,这种就叫动态映射。
#1、创建索引,PUT请求
http://127.0.0.1:9200/student
#2、查看索引映射,GET请求,发现没用映射关系
http://127.0.0.1:9200/student/_mapping
#返回数据
{
"student22": {
"mappings": {}
}
}
#3、插入文档 POST请求
http://127.0.0.1:9200/student/_doc/1001
#请求体
{
"name":"张刚",
"sex":"男",
"age":20
}
#返回数据
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
#4、再次查看映射,发现有映射关系了。返回映射数据
{
"student": {
"mappings": {
"properties": {
"age": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"sex": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
5.2 静态映射
静态映射的意思就是在定义索引后,在把索引中的所有字段类型通过映射提前定义好,那么以后往索引中加数据和字段时,就只能按照规定好的加。
注意:如果加了类型不对等的数据,会报 400 错误。
#1、创建索引,PUT请求
http://127.0.0.1:9200/student2
#2、创建索引映射关系,PUT请求
http://127.0.0.1:9200/student2/_mapping
#请求body
{
"properties": {
"name":{
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": false
},
"age":{
"type": "long",
"index": false
}
}
}
#3、查看索引映射关系,GET请求
http://127.0.0.1:9200/student2/_mapping
#返回数据
{
"student2": {
"mappings": {
"properties": {
"age": {
"type": "long",
"index": false
},
"name": {
"type": "text"
},
"sex": {
"type": "text",
"index": false
}
}
}
}
}
注意:传上面那种body,必须先创建索引,在创建映射关系。下面是索引和映射可以一步做成,区别是body体不一样
#PUT请求
http://127.0.0.1:9200/student3
#body体
{
"settings": {},
"mappings": {
"properties": {
"age": {
"type": "long",
"index": false
},
"name": {
"type": "text",
"analyzer": "ik_smart"
},
"sex": {
"type": "text",
"index": false
}
}
}
}
5.3 映射数据说明
type:类型,ES中支持的数据类型非常丰富,说几个关键的:
String 类型,又分两种:
text:可分词
keyword:不可分词,数据会作为完整字段进行匹配
Numerical:数值类型,分两类
基本数据类型:long、integer、short、byte、double、float、half_float
浮点数的高精度类型:scaled_float
Date:日期类型
Array:数组类型
Object:对象
index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。
true:字段会被索引,则可以用来进行搜索
false:字段不会被索引,不能用来搜索
store:是否将数据进行独立存储,默认为 false
原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
analyzer:指定分词器
5.4 特殊的映射属性说明
下面是我测试的时候遇到的一个映射关系,比如字段name、nickname、sex的fields属性让我很不理解,各种百度查询: 除了本身被映射为text类型,还另外为其添加了名称为keyword、type为keyword的field,这使得查询时既可以对字段本身做Match Query,也可以对author.keyword做Term Query。这里说的查询如果不理解,可以看我下一章的高级查询。
{
"student": {
"aliases": {},
"mappings": {
"properties": {
"age": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"nickname": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"sex": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"settings": {
"index": {
"creation_date": "1689343383825",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "dK-EfgXnST2hiiOrLddH4w",
"version": {
"created": "7080099"
},
"provided_name": "student"
}
}
}
}
5.4 新增映射字段属性
注意:映射属性一旦创建,是不可以修改的,但是可以新增字段映射属性。
#PUT请求,为新增字段content添加映射
http://127.0.0.1:9200/student/_mapping
{
"properties": {
"content": {
"type": "text",
"index": true
}
}
}
六、ES文档操作
6.1 创建文档
#POST请求,1001代表文档ID
http://127.0.0.1:9200/student/_doc/1001
#请求body
{
"age":18,
"name":"张刚",
"sex":"男"
}
6.2 查询文档
#GET请求,1001代表文档ID
http://127.0.0.1:9200/student/_doc/1001
#返回数据
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"age": 18,
"name": "张刚",
"sex": "男"
}
}
6.3 修改文档
和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖。
#POST请求,1001代表文档ID
http://127.0.0.1:9200/student/_doc/1001
#请求body
{
"age":19,
"name":"张刚",
"sex":"男"
}
6.4 修改文档中的某个字段
#POST请求
http://127.0.0.1:9200/student/_update/1001
#请求体
{
"doc": {
"age": 20
}
}
6.5 删除文档
#1、根据ID删除文档
#DELETE请求
http://127.0.0.1:9200/student/_doc/1001
#2、根据条件删除多条文档
http://127.0.0.1:9200/student/_delete_by_query
{
"query":{
"match":{
"age":20
}
}
}
七、分词器(Analyzer)
上面说过ES是通过倒排索引来搜索的,倒排索引中的词和文档建立的关系时,这个"词"就是通过分词器进行切分的。
分词器就是当数据写入ES 时,会把数据切分成不同的词,ES把词和文档列表建立一种映射关系,生成倒排索引。
当进行搜索时,也会对输入的内容进行分词。
7.1 内置分词器
1、不同的分词器会有不同的分词结果,内置的分词器有以下几种,内置分词器对中文的分词都不够友好,一般我们都会用外置中文分词器:IK分词器
分词器 | 描述 |
standard | 默认分词器,如果没有指定,则使用该分析器, 英文按单词词切分,并小写处理 |
simple | 按照单词切分(符号被过滤), 小写处理 |
whitespace | 按照空格切分,不转小写 |
stop | 小写处理,停用词过滤(the,a,is) |
keyword | 不分词,把整个字段当做一个整体返回 |
7.2 中文分词器
在ES中支持中文分词器非常多 如 smartCN、IK 等,推荐的就是 IK分词器。 IK分词器是和ES版本相对应的,这里下载7.8版本的。
分词器 | 描述 |
ik_smart | 会做最粗粒度的拆分 |
ik_max_word | 会将文本做最细粒度的拆分 |
7.2.1 安装分词器
安装步骤: 将IK分词器安装包解压,然后把解压后的文件夹放入 ES 根目录下的 plugins 目录下,重启 ES 即可使用。出现下面截图且启动成功,则证明安装成功。
7.2.2 扩展词汇(自定义词汇)
1、在IK分词器安装包的config目录下,新建mydic.dic文件。注意是IK分词器的config目录,不是ES的config目录,别搞混了。
2、修改mydic.dic文件,一定要重启ES。
3、在IK分词器安装包的config目录下,找到IKAnalyzer.cfg.xml文件,然后把自定义的mydic.dic配进去。
注意: ext_dict表示的扩展词汇,如果配置有"王者荣耀",那么分词中肯定有"王者荣耀"。 ext_stopwords表示停用词,如果配置有"王者荣耀",那么分词中肯定没"王者荣耀"。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">mydic.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
3、引入扩展词汇前进行分词
#请求地址
http://127.0.0.1:9200/_analyze
#请求body
{
"text":"王者荣耀",
"analyzer":"ik_max_word"
}
#返回数据
{
"tokens": [
{
"token": "王者",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "荣耀",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
}
]
}
4、引入扩展词汇后进行分词
#mydic.dic文件内容
王者荣耀
你好
#请求地址
http://127.0.0.1:9200/_analyze
#请求body
{
"text":"王者荣耀",
"analyzer":"ik_max_word"
}
#返回数据
{
"tokens": [
{
"token": "王者荣耀",
"start_offset": 0,
"end_offset": 4,
"type": "CN_WORD",
"position": 0
},
{
"token": "王者",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 1
},
{
"token": "荣耀",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 2
}
]
}
7.3 分词器中的一些用法
7.3.1 _analyze用法
_analyze:指定分词器和文本进行分词测试。
#GET请求
http://127.0.0.1:9200/_analyze
#请求body
{
"analyzer": "ik_max_word",
"text": "王者荣耀"
}
#返回数据
{
"tokens": [
{
"token": "王者",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "荣耀",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
}
]
}
7.3.2 默认分词器说明
2、在创建索引时,指定分词器,如果不指定,默认就是standard分词器。
在查询该索引时,也能查出该索引用的分词器,如果查出的分词器是空的,默认就是standard分词器。下面创建我们指定ik_max_word分词器
#PUT请求
http://127.0.0.1:9200/shopping
#请求body,analyzer就是指定的分词器
{
"settings": {},
"mappings": {
"properties": {
"title":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
#查询索引返回数据
{
"shopping3": {
"aliases": {},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
}
}
},
"settings": {
"index": {
"creation_date": "1689088476639",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "eOeirsuJTpm9j5WEPkIdqg",
"version": {
"created": "7080099"
},
"provided_name": "shopping"
}
}
}
}
7.3.3 查看文档中某一个字段的分词结果
#GET请求
# /{index}/{type}/{_id}/_termvectors?fields=[field]
http://127.0.0.1:9200/student/_doc/1001/_termvectors?fields=name