1. elasticsearch的核心概念
- 什么是elasticsearch
es基于lucence,隐藏复杂性,提供简单易用的restful api接口、java api接口(还有其它语言的api接口),es是一个实时分布式搜索和分析引擎,它用于全文搜索、结构化搜索、分析
-
近实时 从写入数据到可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级(倒排索引)
-
Cluster(集群) 集群包含多个节点,每个节点属于哪个集群是通过一个配置来决定的。对于中小型应用,刚开始一个集群一个节点是正常的
-
Node(节点) 集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为elasticsearch的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群
-
Index (索引) 索引包含一堆相识结构的文档数据,
类比关系型数据库的库
-
Type (类型) 每个索引都可以会有一个或多个Type,type是index中的一个逻辑数据分类,类型类别关系型数据库的表table,
在6.x的版本中是支持type , 但是在7.x的版本中的type都是_doc类型了,在8.x是打算完全去掉type类
-
Document(文档) 文档是es中的最小数据单元,一个document可以是一条客户数据、一条订单数据,
类比关系型数据库的行row
-
Field(字段) field是es的最小单位。一个document里有多个field,每个field就是一个数据字段,
类比关系型数据库的字段
-
Mapping(映射) 数据如何存放到索引对象上,需要有一个映射配置,
类比关系型数据库的schame
-
Shards(分片) 因为ES是个分布式的搜索引擎, 所以索引通常都会分解成不同部分, 而这些分布在不同节点的数据就是分片. ES自动管理和组织分片, 并在必要的时候对分片数据进行再平衡分配, 所以用户基本上不用担心分片的处理细节,一个分片默认最大文档数量是20亿
-
Replica(副本) ES默认为一个索引创建5个主分片, 并分别为其创建一个副本分片. 也就是说每个索引都由5个主分片成本, 而每个主分片都相应的有一个copy
2. curl命令&kibana开发者工具
2.1 curl命令
-
curl介绍 CURL命令简单可以认为是在命令行下访问url的一个工具,是利用URL语法在命令行方式下工作的开源文件传输工具,使用curl可以简单实现常见的get/post请求
-
curl的格式
–curl -X请求类型 请求Url -d '数据'
详细curl命令的讲解可以参考:curl使用操作
- curl操作elasticsearch 因为es的操作符合RESTfull风格,所以可以根据curl对es进行操作
# 如创建索引
curl -XPUT http://192.168.64.129:9200/index11?pretty
# 如删除索引
curl -XDELETE http://192.168.64.129:9200/index11?pretty
2.2 kibana开发者工具
调试elasticsearch也可以采用kibana的开发者工具,这个是调试elasticsearch的最常见的方法
如果没有搭建elasticsearch集群和kibana的同学可以参考:
3. 索引管理
ES索引管理API主要包含如下API:
- Create Index 创建索引:
PUT /index
{
"settings" : { //@1
"number_of_shards" : 1
},
"mappings" : { // @2
"_doc" : {
"properties" : {
"field1" : { "type" : "text" }
}
}
},
"aliases" : { // @3
"alias_1" : {},
"alias_2" : {
"filter" : {
"term" : {"user" : "kimchy" }
},
"routing" : "kimchy"
}
}
}
创建索引采用PUT请求
代码@1:索引的配置属性
代码@2:定义映射,有点类似于关系型数据库中的定义表结构
代码@3:为索引指定别名设置
注意:创建已经存在的索引是要报错的。
- Delete Index 删除索引:
PUT /index
删除索引采用DELETE请求,操作比较简单
- Get index 获取索引:
GET /index
获取索引比较简单
- 查看索引列表
GET /_cat/indices?v
- 更新副本数量
PUT /index/_settings
{
"number_of_replicas": 1
}
- 查看索引配置
GET /index/_settings
4. term & match_all 查询
- term查询
# 插入一条数据
PUT /index/_doc/1
{
"name":"中国人",
"code":"CHN"
}
# 通过term词项查询name字段
GET /index/_search
{
"query": {
"term": {
"name": {
"value": "国"
}
}
},
"from": 0,
"size": 1,
"highlight": {
"fields": {
"name": {}
}
}
}
对于保存在es中的词语,默认采用了分词处理,如:“中国人”,或采才分为“中”,“国”,“人” 三个词项,那么在使用term查询name字段的时候带一个“国”字也是能查询出来的。
注意:如果需要进行分页查询则可以带上from
,size
者两个字段进行分页操作,如果需要进行高亮处理着添加highlight
标识即可
- match_all 看这个查询就能看出来,这个是一个查询全部数据的方法
GET /index/_search
{
"query": {
"match_all": {}
}
}
5. range & exists 查询
- range查询 听这个名字就能听出来,这个是一个范围查询的方法操作比较简答如下:
# range查询age大于等于30 并且 小于等于100 的数据
GET /index/_search
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 100
}
}
}
}
其中range查询可以接受的参数为:
gte:大于等于
gt:大于
lte:小于等于
lt:小于
boost:设置查询的推动值(boost),默认为1.0
- exists查询 exists查询的是某一条数据中包含某一个字段
# 判断index索引中包含由age字段的数据
GET /index/_search
{
"query": {
"exists": {
"field": "age"
}
}
}
6. match 查询
# 采用match查询name字段查询
GET /index/_search
{
"query": {
"match": {
"name": "中李"
}
}
}
解释:其中查询的name字段的内容“中李”会被分词器分为“中”,“李”两个词,只要数据中包含有中李两个字的数据都会被查询出来。所以使用match查询的时候会把查询内容进行分词后进行查询
7. bool查询
为什么需要采用bool查询,因为采用bool查询可以很轻松的查询多个数据的子集,可以进行一些过滤操作,在电商的多条件搜索的时候会使用到。
bool查询主要由以下几种组成:
must:[] : 返回的文档必须满足must子句的条件,并且参与计算分值
filter:[] : 返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
should:[] : 返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match参数定义了至少满足几个子句。
must_nout:[] : 返回的文档必须不满足must_not定义的条件
7.1 bool.must计算
# 搜索index索引下面的数据,采用must查询同时满足name查询 和 age查询两个条件的交集
GET /index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "中李美"
}
},
{
"range": {
"age": {
"gte": 30,
"lte": 100
}
}
}
]
}
}
}
解释:must查询中包含两个查询条件match 和 range两个条件,这个查询是求的两个数据集的子集,并且数据中带有_score分数值,这个分数值越大表明匹配强度越高
7.2 bool.filter计算
# 这个地方采用了bool查询 和 filter查询,这个地方查询的数据和7.1中的查询数据是一致的,唯一不同的就是filter过滤的数据不参与分数_score计算
GET /index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "中李美"
}
}
],
"filter": [
{
"range": {
"age": {
"gte": 30,
"lte": 100
}
}
}
]
}
}
}
filter的过滤和must过滤查询的效果是一样的,只是不参与分数计算
7.3 bool.must_not计算
# 该计算是求: must(数据) - must_not(数据) = 差集数据
GET /index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "中国李美"
}
}
],
"must_not": [
{
"range": {
"age": {
"gte": 30,
"lte": 100
}
}
}
]
}
}
}
解释:可以看到查询出来的数据中,满足了must条件,但是不包含must_not条件中的数据。验证了求的是数据的差集,往往会用到查询了某一批数据后,需要过滤其中一批数据的场景.
7.4 bool.should计算
# 该计算中:包含了满足name条件 或者 age条件的都会查询出来
GET /index/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "中"
}
},
{
"range": {
"age": {
"gte": 30,
"lte": 60
}
}
}
]
}
}
}
解释:should条件是或的关系,只要满足其中一项都会被查询出来
8. 动态mapping
Elasticsearch的一个最重要的特性是,让你尽可能快地开始探索数据。要为文档建立索引,您不必首先创建索引、定义映射类型和定义字段,你只需创建文档,就会自动创建索引,索引、类型和字段
。自动为类型映射根据文档的值推测其类型的过程,就是本文要重点描述的机制:动态类型映射机制。
- 如果遇到新字段,对象就会抛出异常
- 而内部对象
stash
遇到新字段就会动态创建新字段
动态映射机制包含如下两种映射规则:Dynamic field mappings、Dynamic templates
8.1 Dynamic field mappings
动态字段映射规则。默认情况下,当在文档中发现以前未见过的字段时,Elasticsearch将向类型映射添加新字段
JSON datatype | Elasticsearch datatype |
---|---|
null | 不会自动增加类型映射 |
true or false | boolean |
floating point number | float |
integer | long |
object | object |
array | 根据数组中第一个非空值来判断 |
string | date、double、long、text(带有keyword子字段) |
8.2 Dynamic templates
Dynamic field mappings默认情况下是根据elasticsearch支持的数据类型来推测参数值的类型,而动态模板允许您定义自定义映射规则,根据自定义的规则来推测字段值所属的类型,从而添加字段类型映射.
PUT /index
{
"mappings": {
"index": {
"dynamic_templates": [
{ "es": {
"match": "*_es", //@1
"match_mapping_type": "string",
"mapping": {
"type": "string",
"analyzer": "spanish"
}
}},
{ "en": {
"match": "*", //@2
"match_mapping_type": "string",
"mapping": {
"type": "string",
"analyzer": "english"
}
}}
]
}}}
@1:匹配字段名以 _es
结尾的字段
@2:匹配其他所有字符串类型字段
9. 静态mapping
静态mapping主要包括如下的一些字段,这里只列举部分字段。
9.1 修改mapping
PUT /index/_mapping
{
"properties" : {
"age" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"email":{
"type": "keyword"
},
"is_handle":{
"type": "boolean"
}
}
}
9.2 主要字段
- 整型long
- 字符串text (text是会被分词)
- boolean
- date
- keyword (keyword是不会进行分词的,如搜素email或者电话之类)
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
# 解释:其中text为name字段的类型,keyword为其扩展属性,只要不超过256字符也会用keyword进行索引一次,保证精准匹配也能匹配到
其中keyword的搜素方式如下:
# keyword的搜素方式需要在name搜素的后面添加keyword进行搜素
GET /index/_search
{
"query": {
"term": {
"name.keyword": {
"value": "中国人"
}
}
}
}
其他详情介绍请查:官方字段文档
10. 分片 & 副本
- 查看索引的分片
GET /index/_settings
其中的number_of_shards
为当前索引的分片数量,number_of_replicas
为副本数量
- 设置分片和副本的数量 在创建索引的时候就可以设置分片数量:
PUT /test_index
{
"settings" : {
"index" : {
"number_of_shards" : 2,
"number_of_replicas" : 2
}
}
}
- 修改副本数量
PUT /test_index/_settings
{
"index":{
"number_of_replicas" : "3"
}
}
11. 分词器
11.1 默认分词器
- 概念
Analysis(分词):
文本分析是把全文本转换一系列单词(term/token)的过程,也叫分词,Analysis是通过Analyzer来实现的。
analyzer(分析器):
由三种构件块组成的:character filters
,tokenizers
,token filters
character filter字符过滤器
:在一段文本进行分词之前,先进行预处理,比如说最常见的就是,过滤html标签(hello --> hello),& --> and(I&you --> I and you)
tokenizers分词器
:英文分词可以根据空格将单词分开,中文分词比较复杂,可以采用机器学习算法来分词
Token filters Token过滤器:
将切分的单词进行加工,大小写转换(例将“Quick”转为小写),去掉词(例如停用词像“a”、“and”、“the”等等),或者增加词(例如同义词像“jump”和“leap”)
三者顺序
:Character Filters--->Tokenizer--->Token Filter
三者个数
:analyzer = CharFilters(0个或多个) + Tokenizer(恰好一个) + TokenFilters(0个或多个)
- Elasticsearch的内置分词器
Standard Analyzer - 默认分词器,按词切分,小写处理
Simple Analyzer - 按照非字母切分(符号被过滤), 小写处理
Stop Analyzer - 小写处理,停用词过滤(the,a,is)
Whitespace Analyzer - 按照空格切分,不转小写
Keyword Analyzer - 不分词,直接将输入当作输出
Patter Analyzer - 正则表达式,默认\W+(非字符分割)
Language - 提供了30多种常见语言的分词器
Customer Analyzer 自定义分词器
11.2 分词分析
POST _analyze
{
"analyzer": "standard",
"text": "Like X 国庆放假的"
}
11.4 ik分词器
中文的分词器现在大家比较推荐的就是 IK分词器
- 安装
开源分词器 Ik 的github:github.com/medcl/elast…
注意` IK分词器的版本要你安装ES的版本一致
将下载的ik包解压复制到es安装的plugins目录下面即可,再重新启动es就会加载对于的文件
- 使用
ik_smart
: 会做最粗粒度的拆分
ik_max_word
: 会将文本做最细粒度的拆分
11.5 热词配置
进入es的plugins目录的ik分词器的config目录
[root@localhost config]# cd /data/elasticsearch-7.15.0/plugins/ik/config/
[root@localhost config]#
[root@localhost config]# cat 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">extar_my.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">stop_my.dic</entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://192.168.64.129/hot.dic</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
[root@localhost config]#
- 扩展热词
在目录下添加extar_my.dic
文件,内容为可以自定义,然后再修改IKAnalyzer.cfg.xml
文件将配置的热词添加到配置文件中
<entry key="ext_stopwords">extar_my.dic</entry>
- 停用词
在目录下添加stop_my.dic
文件,内容为可以自定义,然后再修改IKAnalyzer.cfg.xml
文件将配置的热词添加到配置文件中, 添加了停用词典则词典中的词语将不再进行分词
<entry key="ext_stopwords">stop_my.dic</entry>
- 远程加载热词
加载一个远程的词典文件,es会隔几秒钟,就会去拉起远程文件加载进去,所以如果有热词跟新,只需要修改远程文件中的热词即可,无需重启es.
<entry key="remote_ext_dict">http://192.168.64.129/hot.dic</entry>