> 技术文档 > Elasticsearch(看这一篇就够了)

Elasticsearch(看这一篇就够了)


目录:

  • Elasticsearch
    • 介绍
    • 正排索引和倒排索引
    • Elasticsearch安装
      • 安装ES服务
      • 安装服务
      • 安装kibana
    • 索引操作
      • 创建索引
      • 查询索引库
      • 修改索引库
      • 删除索引库
    • Elasticsearch常用操作
      • 文档操作
        • 新增文档
        • 查询文档
        • 删除文档
        • 根据id批量查询文档
        • 查询所有文档
        • 修改文档部分字段
    • 域的属性
    • 分词
      • 默认分词器
      • IK分词器
      • 拼音分词器
      • 自定义分词器
    • Elasticsearch搜索文档
      • 搜索方式
    • SpringDaraES案例
      • 使用Repository继承的方法查询文档
      • 使用DSL语句查询文档
      • 按照规则命名方法查询文档
      • 分页查询
      • 结果排序
      • template工具类
        • 操作索引
        • 操作文档
        • 查询文档
        • 复杂条件查询
        • 分页查询
        • 结果排序
    • Elasticsearch集群
      • 搭建集群
      • 测试集群状态
      • 故障应对和水平扩容
      • 内存设置
      • 磁盘选择
      • 分片策略
    • Elasticsearch案例
      • 需求说明
      • ES自动补全
      • 创建索引
      • mysql数据导入es
      • 项目搭建
      • 创建实体类
      • 创建Repository接口
      • 自动补全功能
      • 搜索关键字功能
      • 创建Controller类
      • 前端页面

Elasticsearch(看这一篇就够了)

Elasticsearch

介绍

Elasticsearch(看这一篇就够了)
Elasticsearch是一个全文检索服务器

全文检索是一种非结构化数据的搜索方式

  • 结构化数据:指具有固定格式固定长度的数据,如数据库中的字段。

  • 非结构化数据:指格式和长度不固定的数据,如电商网站的商品详情。

结构化数据一般存入数据库,使用sql语句即可快速查询。但由于非结构化数据的数据量大且格式不固定,我们需要采用全文检索的方式进行搜索。全文检索通过建立倒排索引加快搜索效率。

正排索引和倒排索引

索引

将数据中的一部分信息提取出来,重新组织成一定的数据结构,我们可以根据该结构进行快速搜索,这样的结构称之为索引。

索引即目录,例如字典会将字的拼音提取出来做成目录,通过目录即可快速找到字的位置。

索引分为正排索引倒排索引

正排索引(正向索引)
将文档id建立为索引,通过id快速可以快速查找数据。如数据库中的主键就会创建正排索引。
Elasticsearch(看这一篇就够了)

倒排索引(反向索引)
非结构化数据中我们往往会根据关键词查询数据。此时我们将数据中的关键词建立为索引,指向文档数据,这样的索引称为倒排索引。
Elasticsearch(看这一篇就够了)

Elasticsearch安装

安装ES服务

准备工作
1.准备一台搭载有CentOS7系统的虚拟机,使用XShell连接虚拟机

2.关闭防火墙,方便访问ES

#关闭防火墙:systemctl stop firewalld.service#禁止防火墙自启动:systemctl disable firewalld.service

3.配置最大可创建文件数大小

#打开系统文件:vim /etc/sysctl.conf#添加以下配置:vm.max_map_count=655360#配置生效:sysctl -p
  1. 由于ES不能以root用户运行,我们需要创建一个非root用户,此处创建一个名为es的用户:
#创建用户:useradd es

安装服务

  1. 使用rz命令将linux版的ES上传至虚拟机

  2. 解压ES

#解压:tar -zxvf elasticsearch-8.10.4-linux-x86_64.tar.gz#重命名:mv elasticsearch-8.10.4 elasticsearch1#移动文件夹:mv elasticsearch1 /usr/local/#es用户取得该文件夹权限:chown -R es:es /usr/local/elasticsearch1
  1. 启动ES服务:
#切换为es用户:su es#进入ES安装文件夹:cd /usr/local/elasticsearch1/bin/#启动ES服务:./elasticsearch 
  1. 当启动成功,可以看到类似以下的日志输出。首次启动Elasticsearch,默认会启用安全配置功能,启用身份认证和授权,内置超级用户elastic,并生成默认密码,此时要注意保存,否则之后启动不会再显示。
    Elasticsearch(看这一篇就够了)
# 重置默认密码:cd /usr/local/elasticsearch1/bin/./elasticsearch-reset-password -u elastic# 自定义密码:cd /usr/local/elasticsearch1/bin/./elasticsearch-reset-password --username elastic -i
  1. 连接ES,查询ES服务是否启动成功
# 参数 --cacert指定了证书curl --cacert /usr/local/elasticsearch1/config/certs/http_ca.crt -u elastic https://localhost:9200

安装kibana

Kibana是一款开源的数据分析和可视化平台,设计用于和Elasticsearch协作。我们可以使用Kibana对Elasticsearch索引中的数据进行搜索、查看、交互操作。

  1. 使用rz工具将Kibana压缩文件上传到Linux虚拟机

  2. 解压

tar -zxvf kibana-8.10.4-linux-x86_64.tar.gz -C /usr/local/
  1. 修改配置
# 进入Kibana解压路径cd /usr/local/kibana-8.10.4/config# 修改配置文件vim kibana.yml# 加入以下内容# 主机IP,服务名server.host: \"虚拟机IP\"server.name: \"kibana\"
  1. 启动:

kibana不能以root用户运行,我们给es用户设置kibana目录的权限,并使用es用户运行kibana

# 给es用户设置kibana目录权限chown -R es:es /usr/local/kibana-8.10.4/# 切换为es用户su es# 启动kibanacd /usr/local/kibana-8.10.4/bin/./kibana
  1. 访问kibana:http://虚拟机IP:5601
    首次访问Kibana管理台会提示输入ES生成的token秘钥,可以在ES首次启动日志中找。

Elasticsearch(看这一篇就够了)
如果token已失效或不正确,你也可以重新生成token。

# 进入es安装目录cd /usr/local/elasticsearch1/bin# 重新生成kibana的token.elasticsearch-create-enrollment-token --scope kibana

紧接着输入登录账号 elastic,密码也同样是从ES首次启动日志中找。

  1. 点击Management => Index Management可以查看es索引信息。

索引操作

创建索引

Elasticsearch是使用RESTful风格的http请求访问操作的,请求参数和返回值都是Json格式的,我们可以使用kibana发送http请求操作ES。

创建没有结构的索引
路径:ip地址:端口号/索引名

注:在kibana中所有的请求都会省略ip地址:端口号,之后的路径我们省略写ip地址:端口号

格式:

PUT /索引库名称{  \"mappings\": {  \"properties\": {  \"字段名\":{  \"type\": \"text\", \"analyzer\": \"ik_smart\" }, \"字段名2\":{  \"type\": \"keyword\", \"index\": \"false\" }, \"字段名3\":{  \"properties\": {  \"子字段\": {  \"type\": \"keyword\" } } }, // ...} }}

基本语法:

  • 请求方式:PUT
  • 请求路径:/索引库名,可以自定义
  • 请求参数:mapping映射

格式

为索引添加结构

POST /索引名/_mapping{  \"properties\":{  \"域名1\":{  \"type\":域的类型, \"store\":是否存储, \"index\":是否创建索引, \"analyzer\":分词器 }, \"域名2\":{  ... } }}
PUT /索引库名称{  \"mappings\": {  \"properties\": {  \"字段名\":{  \"type\": \"text\", \"analyzer\": \"ik_smart\" }, \"字段名2\":{  \"type\": \"keyword\", \"index\": \"false\" }, \"字段名3\":{  \"properties\": {  \"子字段\": {  \"type\": \"keyword\" } } }, // ...} }}

查询索引库

基本语法

  • 请求方式:GET
  • 请求路径:/索引库名
  • 请求参数:无

格式

GET /索引库名

修改索引库

倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改mapping

虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。

语法说明

PUT /索引库名/_mapping{  \"properties\": {  \"新字段名\":{  \"type\": \"integer\" } }}

删除索引库

语法

  • 请求方式:DELETE

  • 请求路径:/索引库名

  • 请求参数:无

格式

DELETE /索引库名

Elasticsearch常用操作

文档操作

新增文档
POST /索引/_doc/[id值]{  \"field名\":field值}POST /索引库名/_doc/文档id{  \"字段1\": \"值1\", \"字段2\": \"值2\", \"字段3\": {  \"子属性1\": \"值3\", \"子属性2\": \"值4\" }, // ...}

示例:

POST /jjy/_doc/1{  \"info\": \"jjy最牛啦\", \"email\": \"zy@itcast.cn\", \"name\": {  \"firstName\": \"云\", \"lastName\": \"赵\" }}

注:id值不写时自动生成文档id,id和已有id重复时修改文档

查询文档
GET /索引/_doc/id值

示例:

GET /jjy/_doc/1
删除文档
DELETE /索引/_doc/id值

示例:

DELETE /jjy/_doc/1
根据id批量查询文档
GET /索引/_mget{  \"docs\":[ { \"_id\":id值}, { \"_id\":id值} ] }

示例:

GET /jjy/_mget{  \"docs\":[ { \"_id\":1}, { \"_id\":2} ] }
查询所有文档
GET /索引/_search{  \"query\": {  \"match_all\": { } }}

示例:

GET /jjy/_search{  \"query\": {  \"match_all\": { } }}
修改文档部分字段
POST /索引/_update/1/{  \"doc\":{  域名:值 } }

示例:

POST /jjy/_update/id值/{  \"doc\":{  info:\"jjy好厉害哦\" } }

注:

Elasticsearch执行删除操作时,ES先标记文档为deleted状态,而不是直接物理删除。当ES存储空间不足或工作空闲时,才会执行物理删除操作。

Elasticsearch执行修改操作时,ES不会真的修改Document中的数据,而是标记ES中原有的文档为deleted状态,再创建一个新的文档来存储数据。

域的属性

index

该域是否创建索引。只有值设置为true,才能根据该域的关键词查询文档。// 根据关键词查询文档GET /索引名/_search{  \"query\":{  \"term\":{  搜索字段: 关键字 } }}

type

域的类型

核心类型 具体类型 字符串类型 text 整数类型 long, integer, short, byte 浮点类型 double, float 日期类型 date 布尔类型 boolean 数组类型 array 对象类型 object 不分词的字符串 keyword

store
是否单独存储。如果设置为true,则该域能够单独查询。

// 单独查询某个域:GET /索引名/_search{  \"stored_fields\": [\"域名\"]}

分词器

默认分词器

ES文档的数据拆分成一个个有完整含义的关键词,并将关键词与文档对应,这样就可以通过关键词查询文档。要想正确的分词,需要选择合适的分词器。

standard analyzer:Elasticsearch默认分词器,根据空格和标点符号对英文进行分词,会进行单词的大小写转换。

  • 查看分词效果
GET /_analyze{  \"text\":测试语句, \"analyzer\":分词器}

IK分词器

IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。提供了两种分词算法:

  • ik_smart:最少切分

  • ik_max_word:最细粒度划分

安装IK分词器

  1. 关闭es服务

  2. 使用rz命令将ik分词器上传至虚拟机

注:ik分词器的版本要和es版本保持一致。

  1. 解压ik分词器到elasticsearch的plugins目录下

unzip elasticsearch-analysis-ik-8.10.4.zip -d /usr/local/elasticsearch1/plugins/analysis-ik

  1. 启动ES服务
su es#进入ES安装文件夹:cd /usr/local/elasticsearch1/bin/#启动ES服务:./elasticsearch

测试分词器效果

GET /_analyze{  \"text\":\"测试语句\", \"analyzer\":\"ik_smart/ik_max_word\"}

IK分词器词典
IK分词器根据词典进行分词,词典文件在IK分词器的config目录中。

  • main.dic:IK中内置的词典。记录了IK统计的所有中文单词。

  • IKAnalyzer.cfg.xml:用于配置自定义词库。

 IK Analyzer 扩展配置</comment> <!--用户可以在这里配置自己的扩展字典 --> <entry key=\"ext_dict\">ext_dict.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key=\"ext_stopwords\">ext_stopwords.dic</entry> <!--用户可以在这里配置远程扩展字典 --> <!-- <entry key=\"remote_ext_dict\">words_location</entry> --> <!--用户可以在这里配置远程扩展停止词字典--> <!-- <entry key=\"remote_ext_stopwords\">words_location</entry> --></properties>

拼音分词器

拼音分词器可以将中文分成对应的全拼,全拼首字母等。

安装拼音分词器

  1. 关闭es服务

  2. 使用rz命令将拼音分词器上传至虚拟机

注:拼音分词器的版本要和es版本保持一致。

解压pinyin分词器到elasticsearch的plugins目录下

unzip elasticsearch-analysis-pinyin-8.10.4 -d /usr/local/elasticsearch1/plugins/analysis-pinyin
启动ES服务

su es#进入ES安装文件夹:cd /usr/local/elasticsearch1/bin/#启动ES服务:./elasticsearch

测试分词效果

GET /_analyze{  \"text\":测试语句, \"analyzer\":\"pinyin\"}

自定义分词器

真实开发中我们往往需要对一段内容既进行文字分词,又进行拼音分词,此时我们需要自定义ik+pinyin分词器。

创建自定义分词器
在创建索引时自定义分词器

PUT /索引名{  \"settings\" : {  \"analysis\" : {  \"analyzer\" : {  \"ik_pinyin\" : {  //自定义分词器名 \"tokenizer\":\"ik_max_word\", // 基本分词器 \"filter\":\"pinyin_filter\" // 配置分词器过滤 } }, \"filter\" : {  // 分词器过滤时配置另一个分词器,相当于同时使用两个分词器 \"pinyin_filter\" : {   \"type\" : \"pinyin\", // 另一个分词器 // 拼音分词器的配置 \"keep_separate_first_letter\" : false, // 是否分词每个字的首字母 \"keep_full_pinyin\" : true, // 是否分词全拼 \"keep_original\" : true, // 是否保留原始输入 \"remove_duplicated_term\" : true // 是否删除重复项 } } } }, \"mappings\":{  \"properties\":{  \"域名1\":{  \"type\":域的类型, \"store\":是否单独存储, \"index\":是否创建索引, \"analyzer\":分词器 }, \"域名2\":{  ... } } }}

测试自定义分词器

GET /索引/_analyze{  \"text\": \"你好程序员\", \"analyzer\": \"ik_pinyin\"}

Elasticsearch搜索文档

添加一些文档数据

PUT /students{  \"mappings\":{  \"properties\":{  \"id\": {  \"type\": \"integer\", \"index\": true }, \"name\": {  \"type\": \"text\", \"store\": true, \"index\": true, \"analyzer\": \"ik_smart\" }, \"info\": {  \"type\": \"text\", \"store\": true, \"index\": true, \"analyzer\": \"ik_smart\" } } }}POST /students/_doc/{  \"id\":1, \"name\":\"程序员\", \"info\":\"I love baizhan\"}POST /students/_doc/{  \"id\":2, \"name\":\"美羊羊\", \"info\":\"美羊羊是羊村最漂亮的人\"}POST /students/_doc/{  \"id\":3, \"name\":\"懒羊羊\", \"info\":\"懒羊羊的成绩不是很好\"}POST /students/_doc/{  \"id\":4, \"name\":\"小灰灰\", \"info\":\"小灰灰的年纪比较小\"}POST /students/_doc/{  \"id\":5, \"name\":\"沸羊羊\", \"info\":\"沸羊羊喜欢美羊羊\"}POST /students/_doc/{  \"id\":6, \"name\":\"灰太狼\", \"info\":\"灰太狼是小灰灰的父亲,每次都会说我一定会回来的\"}

搜索方式

match_all:查询所有文档

{  \"query\":{  \"match_all\":{ } }}

match:全文检索。将查询条件分词后再进行搜索。

{  \"query\":{  \"match\":{  搜索字段:搜索条件 } }}

注:在搜索时关键词有可能会输入错误,ES搜索提供了自动纠错功能,即ES的模糊查询。使用match方式可以实现模糊查询。模糊查询对中文的支持效果一般,我们使用英文数据测试模糊查询。

{  \"query\": {  \"match\": {  \"域名\": {  \"query\": 搜索条件, \"fuzziness\": 最多错误字符数,不能超过2 } } }}

range:范围搜索。对数字类型的字段进行范围搜索

{  \"query\":{  \"range\":{  搜索字段:{  \"gte\":最小值