阅读 112

elasticsearch-核心知识

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 复制代码

image.png

image.png

2.2 kibana开发者工具

调试elasticsearch也可以采用kibana的开发者工具,这个是调试elasticsearch的最常见的方法

image.png

如果没有搭建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 复制代码

image.png

  • 更新副本数量

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": {}     }   } } 复制代码

image.png

对于保存在es中的词语,默认采用了分词处理,如:“中国人”,或采才分为“中”,“国”,“人” 三个词项,那么在使用term查询name字段的时候带一个“国”字也是能查询出来的。

注意:如果需要进行分页查询则可以带上fromsize者两个字段进行分页操作,如果需要进行高亮处理着添加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": "中李"     }   } } 复制代码

image.png

解释:其中查询的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             }           }         }       ]     }   } } 复制代码

image.png

解释: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             }           }         }       ]     }   } } 复制代码

image.png

解释:可以看到查询出来的数据中,满足了must条件,但是不包含must_not条件中的数据。验证了求的是数据的差集,往往会用到查询了某一批数据后,需要过滤其中一批数据的场景.

7.4 bool.should计算

# 该计算中:包含了满足name条件 或者 age条件的都会查询出来 GET /index/_search {   "query": {     "bool": {       "should": [         {           "match": {             "name": "中"           }         },         {           "range": {             "age": {               "gte": 30,               "lte": 60             }           }         }       ]     }   } } 复制代码

解释:should条件是或的关系,只要满足其中一项都会被查询出来

image.png

8. 动态mapping

Elasticsearch的一个最重要的特性是,让你尽可能快地开始探索数据。要为文档建立索引,您不必首先创建索引、定义映射类型和定义字段,你只需创建文档,就会自动创建索引,索引、类型和字段。自动为类型映射根据文档的值推测其类型的过程,就是本文要重点描述的机制:动态类型映射机制。

  • 如果遇到新字段,对象就会抛出异常

  • 而内部对象 stash 遇到新字段就会动态创建新字段

动态映射机制包含如下两种映射规则:Dynamic field mappings、Dynamic templates


8.1 Dynamic field mappings

动态字段映射规则。默认情况下,当在文档中发现以前未见过的字段时,Elasticsearch将向类型映射添加新字段

JSON datatypeElasticsearch datatype
null不会自动增加类型映射
true or falseboolean
floating point numberfloat
integerlong
objectobject
array根据数组中第一个非空值来判断
stringdate、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 复制代码

image.png

其中的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 国庆放假的" } 复制代码

image.png

11.4 ik分词器

中文的分词器现在大家比较推荐的就是 IK分词器

  • 安装

开源分词器 Ik 的github:github.com/medcl/elast…
注意` IK分词器的版本要你安装ES的版本一致

将下载的ik包解压复制到es安装的plugins目录下面即可,再重新启动es就会加载对于的文件

  • 使用

ik_smart: 会做最粗粒度的拆分

image.png

ik_max_word: 会将文本做最细粒度的拆分 image.png

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]#  复制代码

  • 扩展热词

image.png

在目录下添加extar_my.dic文件,内容为可以自定义,然后再修改IKAnalyzer.cfg.xml 文件将配置的热词添加到配置文件中

<entry key="ext_stopwords">extar_my.dic</entry> 复制代码

  • 停用词

image.png

在目录下添加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>


作者:beyondfeng
链接:https://juejin.cn/post/7019622105381601294


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐