Elasticsearch入门笔记

7 篇文章 0 订阅

搜索引擎

搜索引擎需要有一个数据源,这里就需要一个数据采集和数据同步的过程(来自数据库、爬虫等)。针对这些数据进行处理后存放到相应的搜索引擎节点上,从而为用户提供检索服务。它存在的目的就是优化用户体验,精准地提供有效的搜索服务、对用户搜索行为进行分析。

  • Lucene:是 Java 类库,实现集群复杂
  • Solr:基于 Lucene
  • Elasticsearch:ES 基于 Lucene,提供 Restful 风格的接口进行操作,所以可对接其它开发语言

1 ES 核心术语、概念

  • 索引 index:一组集合,可以看作为关系型数据库中的表
  • 文档 document:以 JSON 的形式存在,一个文档就是一条记录,可以看作为关系型数据库中的数据行
  • 字段 fields:文档的属性,可以看作为关系型数据库中的数据列即字段名
  • 映射 mapping:字段的表结构定义(是否为主键,数据类型,是否可为 null 等)
  • 近实时 NRTNear real time 指的是新的文档、新的索引新增后,此时用户搜索会有一定的延迟,延迟时间大概一秒左右,可以忽略不计,从而看做接近实时
  • 节点 node:集群中的每一个搜索引擎服务器,
  • shardreplica:ES 集群架构原理
    • shard 数据分片:把索引库拆分为多份,分别放在不同的节点上。即这些不同的节点的索引库的数据内容加在一起才是一个完整的索引库,目的为了水平扩展和提高吞吐量
    • replica 备份:由于节点的数据结合起来才是所有数据,所以就要做好节点宕机的准备,这里就需要使用 replica,即每个 shard 的备份,所以此时就分为:主分片 primary shard 和 备份分片 replica shard
  • 倒排索引:在实际应用中需要根据属性(字段)的值来查找数据,返回的索引表中的每一项都包含一个属性值和该属性值的各个记录地址(下图蓝色圈)。这种不是根据查询到的数据来确定属性,而是根据属性来确定数据的位置,就称为倒排索引。
    在这里插入图片描述

当副本数大于数据节点数时,那么每个分片只能最多有 节点数量-1 个副本,无法分配的副本数则为 主分片数*(副本数-(节点数-1)),例如:假设节点数为3,主分片数为5,副本数为3,那么无法分配的副本数则为:5*(3-(3-1))=5。那么此时只需要重新设置索引副本分片数即可。参考文章:《Elasticsearch(ES)生产集群健康状况为黄色(yellow)的官方详细解释、原因分析和解决方案(实测可用)》

2 安装 Elasticsearch

官网 下载 6.4.3 版本的安装包,因为后期整合SpringBoot,它目前支持的最高版本就是 6.4.3 ,解压缩后在解压缩目录下创建一个名为 data 的文件夹,此时当前目录下有以下文件目录:

  • bin:包含可执行文件
  • config:配置文件目录
  • JDK:java 环境
  • lib:依赖的 jar,类库
  • logs:日志文件目录
  • modules:ES 相关的模块
  • plugins:可以自开发的插件存放的地方
  • data:存放数据(索引表)的地方

修改存放在 config 目录下核心配置文件 elasticsearch.yml

# 集群名称
cluster.name: seiei-elasticsearch
# 当前 ES 节点的名称
node.name: es-node0
# 修改存放索引表的目录
path.data: /usr/local/elasticsearch/data
# 修改日志文件目录
path.logs: /usr/local/elasticsearch/logs
# 同 Redis,设置 0.0.0.0 代表可以让远程连接,不受 ip 限制
network.host: 0.0.0.0
# 设置跨域
http.cors.enabled: true
http.cors.allow-origin: "*"

由于我这边是在虚拟机运行所以还需要修改一下 JVM 参数,打开 config 目录下的 jvm.options 文件,作以下修改:

# 运行内存设置,默认1G,可使用虚拟机就修改为 128M
-Xms128m
-Xmx128m

由于 ES 不允许使用 root 用户操作,所以需要切换用户,将 ES 的用户权限属性进行修改:

chown -R seiei:seiei /usr/local/elasticsearch 

这时启动 ES 可能还会发生以下错误:在这里插入图片描述
那么还需要修改一下 Linux 配置

vim /etc/security/limits.conf

添加以下配置

* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096

打开以下文件

vim /etc/sysctl.conf

添加以下配置:

vm.max_map_count=262145

使用以下命令刷新一下配置

sysctl -p

最后输入一下命令,在后台启动一下 ES

./elasticsearch -d

关闭 ES,可以使用 jps 命令能显示当前所有 java 进程的 pid,从而杀掉 ES 进程。如果没有 jps 命令,需要 yum install java-1.8.0-openjdk-devel.x86_64 安装。

3 使用 restful API 基本操作

使用谷歌插件 elasticsearch head 可提供可视化操作 ES。
使用以下 API 可获取集群节点的运行情况:green 表示所有分片都可以正常运行;yellow 表示所有主分片都可以正常运行,但部分备用分片不能正常运行;red 表示部分主分片不能正常运行

GET /_cluster/health

3.1 操作索引表

  • 查看所有索引表
GET /_cat/indices?v
  • 查询某个索引表
GET /indexName
  • 构建索引表,其中
PUT /{indexName}
{
  "settings": {
    "index": {
      "number_of_shards": "3", // 主分片个数
      "number_of_replicas": "2" // 备用分片个数
    }
  },
  // 设置 Mapping
  "mappings": {
    "properties": {
      "realname": {
        "type": "text",
        "index": true // 如果设置为 false 的话,该字段就不会被索引
      }, 
      "nickname": {
        "type": "keyword",
        "index": false
      }
    }
  }
}
  • 删除索引表
DELETE /{indexName}

3.2 操作 Mappings

  • 为已存在的索引表创建 Mappings,索引表的某个属性一旦被建立,就不能修改,只可以新增额外的属性type 的属性有:textkeywordlongintegerfloatdoublebyteshorttextbooleandateobject
POST /{indexName}/_mapping
{
  "properties": {
    {fieldName}: {
      "type": {typeName}
    }
  }
}

textkeyword 的区别:如果 Mappings 的 type 设置为 text,使用分词分析命令时,就可以看到会返回 analyzeTxt 拆分词列表,即会进行分词、倒排索引;如果设置为 keyword,则会直接返回 analyzeTxt 不作拆分词操作,精准匹配:

POST /{indexName}/_analyze
{
	"field": {fieldName}
	"text": {analyzeTxt}
}

3.3 操作文档

  • 添加文档,如果索引表没有手动建立对应 Mappings,那么当插入文档数据的时候,会根据文档类型自动设置属性类型。这个就是 ES 的动态映射,帮我们在索引库中建立对应的数据结构相关配置信息。
POST /{indexName}/_doc/{id}
{
	{fieldName1}: {fieldValue1}
	{fieldName2}: {fieldValue2}
	...
}

要注意的是上面的 id 指的是 ES 中的 id,如果不指定,ES 会自动生成一个字符串,建议这里的 id 和设置数据的 id 保持一致。
看下图是由 ES 自动映射生成的索引表,name 字段属性下还有有一个 fields 属性,里头声明了 "type": "keyword",这是代表对一个字段设置多种索引模式,即使用 text 类型做全文分词检索,也可以使用 keyword 类型做聚合和排序;而 "ignore_above": 256 表示字段索引和存储的长度最大值,超过则被忽略。
在这里插入图片描述

  • 删除文档,文档删除是逻辑删除,文档还是保存在磁盘上,随着数据越来越多,才会把那些曾经标识过删除的,从磁盘清理出去
DELETE /{indexName}/_doc/{id}
  • 修改文档
    使用以下接口进行 全量替换,如果修改前有设置过字段 A 的值,而修改时没有指定字段 A 的值,那么最后的结果会导致该数据的字段 A 的值为空。
PUT /{indexName}/_doc/{id}
{
	{fieldName1}: {fieldValue1},
	{fieldName2}: {fieldValue2},
	...
}

使用以下接口进行 局部替换

POST /{indexName}/_doc/{id}/_update
{
	"doc": {
		{fieldName1}: {fieldValue1},
		{fieldName2}: {fieldValue2},
		...
	}
}
  • 查看某个 id 的文档是否存在,存在返回 200,不存在返回 404,这样的查询会更节省流量
HEAD /{indexName}/_doc/{id}
  • 查询文档,根据 id 查询
// 查询全部字段
GET /{indexName}/_doc/{id}
// 查询部分字段
GET /{indexName}/_doc/{id}?_source=fieldName1,fieldName2...

查询全部数据:

// 查询全部字段
GET /{indexName}/_doc/_search
// 查询部分字段
GET /{indexName}/_doc/_search?_source=fieldName1,fieldName2...

其中获取到的数据以下划线开头的字段数据是 元数据

  • _index:文档数据所属的索引表
  • _type:文档数据属于哪个类型,7.x 版本的 ES 一概为 _doc
  • _id:文档数据的唯一标识,主键
  • _score:查询相关度,是否契合用户匹配,分数越高用户的搜索体验越高
  • _source:文档查询到的数据
  • _seq_no:文档版本号(针对某个主分片内分配的编号)
  • _primary_term:文档所在位置(针对的是哪个主分片)
  • _version:版本号,旧版本使用它来作为上乐观锁依据,新版本使用 _seq_no_primary_term 联合作为上锁依据,通俗的说,可以把 _version 看做学校对每个学生都进行了编号,而 _seq_no_primary_term 则是先对学生做一个班级分类(_primary_term),再在班级分类里对学生进行编号,这样的效率会更加高效,管理也会更方便

指定 _seq_no_primary_term,模拟两个客户端同时操作同一个文档数据, _seq_no_primary_term 发生了冲突

POST /{indexName}/_doc/{_id}/_update?if_seq_no={数值}&if_primary_term={数值}

4 分词器

4.1 分词和内置分词器

把文本转换为一个个的单词,分词又称为 analysis,ES 默认只对英文语句做分词,而不支持中文,每个中都会被拆分为独立的个体。

  • 全局分词分析
POST /_analyze
{
	"analyzer": {analyzerType},
	"text": {analyzeText}
}
  • 对于某个索引表的数据属性进行分词分析
POST /{indexName}/_analyze
{
	"analyzer": {analyzerType},
	"field": {fieldName},
	"text": {analyzeText}
}

其中 analyzer 是指分词器,ES 的内置分词器有:

  • standard:默认分词,单词会被拆分,大写会转化为小写
  • simple:按照非字母分词,即 don't 会分词为:dont,大写会转为小写
  • whitespace:根据按照空格分词,忽略大小写
  • stop:去除无意义的单词,如 theais
  • keyword:不作分词处理,整个文本作为一个单独的关键词

4.2 配置 IK 中文分词器

github 上下载对应的 IK 压缩包(版本号要一致,用户权限),然后解压到 ES 安装目录下的 plugins/ik 目录下,然后重启动 ES 即可:

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

重启后就可以使用以下两个分词器来分析中文:

  • ik_max_word:会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合
  • ik_smart:会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”

自定义词典:

  • 修改配置文件
vim /usr/local/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml
  • 添加自定义词典
<?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">seieiCustom.dic</entry>
     <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords"></entry>
    <!--用户可以在这里配置远程扩展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry> -->
    <!--用户可以在这里配置远程扩展停止词字典-->
    <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
  • 在同级目录下创建自定义词典文件 seieiCustom.dic 如:
骚年
蚌埠住
  • 重启 ES

注:

在设置 Mappings 时,可以在字段设置 analyzerik_max_word,用户对文档进行分词检索时,首先用户的搜索词汇进行一次分词操作,而文档对应的字段如果设置了分词器属性,它自身就会做一个分词操作(初始化的文档的时候),然后对二者进行一个比较。
如下设置分词器属性:

POST /{indexName}/_mapping
{
	"properties": {
		"name": {
				"type": "text",
				"analyzer": "ik_max_word"
		}
	}
}

在更新、添加了自定义词典后,先前创建了的文档(设置了对应分词器)不会自动更新对应的词典,此时需要手动更新:

POST /{indexName}/_update_by_query?conflicts=proceed
// 多个索引表更新
POST /{indexName1},{indexName2}../_update_by_query?conflicts=proceed
// 更新 index 为前缀的索引表
POST /index*/_update_by_query?conflicts=proceed
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值