ElasticSearch
ElasticSearch:ES是一个基于Lucene实现的开源、分布式、Restful的全文本搜索引擎;此外,它还是一个分布式实时文档存储,其中每个文档的每个field均是被索引的数据,且可被搜索;也是一个带实时分析功能的分布式搜索引擎,能够扩展至数以百计的节点实时处理PB级的数据。
基本组件:
索引(index):文档容器,换句话说,索引是具有类似属性的文档的集合。类似于表。索引名必须使用小写字母;
类型(type):类型是索引内部的逻辑分区,其意义完全取决于用户需求。一个索引内部可定义一个或多个类型。一般来说,类型就是拥有相同的域的文档的预定义。
文档(document):文档是Lucene索引和搜索的原子单位,它包含了一个或多个域。是域的容器;基于JSON格式表示。
每个域的组成部分:一个名字,一个或多个值;拥有多个值的域,通常称为多值域;
映射(mapping):原始内容存储为文档之前需要事先进行分析,例如切词、过滤掉某些词等;映射用于定义此分析机制该如何实现;除此之外,ES还为映射提供了诸如将域中的内容排序等功能。
ES的集群组件:
Cluster:ES的集群标识为集群名称;默认为"elasticsearch"。节点就是靠此名字来决定加入到哪个集群中。一个节点只能属性于一个集群。
Node:运行了单个ES实例的主机即为节点。用于存储数据、参与集群索引及搜索操作。节点的标识靠节点名。
Shard:将索引切割成为的物理存储组件;但每一个shard都是一个独立且完整的索引;创建索引时,ES默认将其分割为5个shard,用户也可以按需自定义,创建完成之后不可修改。
shard有两种类型:primary shard和replica。Replica用于数据冗余及查询时的负载均衡。每个主shard的副本数量可自定义,且可动态修改。
ES Cluster工作过程:
启动时,通过多播(默认)或单播方式在9300/tcp查找同一集群中的其它节点,并与之建立通信。
集群中的所有节点会选举出一个主节点负责管理整个集群状态(必要时启动修复过程,主节点会检查所有可用主shared,并确定是否存在可用,如果异常集群会转换成yellow模式,此时个副本shared均处于未分配模式都不可用使吞吐能力下降,然后会选择一个副本shared提升为主shared,检查副本shared数量缺失会自动复制数据添加,一切完成之后集群状态转为green),以及在集群范围内决定各shards的分布方式。站在用户角度而言,每个均可接收并响应用户的各类请求。
集群有状态:green, red, yellow
官方站点:https://www.elastic.co/
安装:
JDK:
Oracle JDK
OpenJDK
yum -y install java-1.8.0-openjdk-1.8.0.362.b08-1.el7_9.x86_64 java-1.8.0-openjdk-devel.x86_64 java-1.8.0-openjdk-headless.x86_64
rpm -ivh elasticsearch-1.7.2.noarch.rpm
vim /etc/elasticsearch/elasticsearch.yml #修改集群名和节点名字
cluster.name: elk
node.name: "elk1"
systemctl daemon-reload
systemctl start elasticsearch.service
systemctl status elasticsearch.service
ss -tnl #出现9200、9300端口
ES的默认端口:
参与集群的事务:9300/tcp
transport.tcp.port
接收请求:9200/tcp
http.port
Restful API:
四类API:
(1) 检查集群、节点、索引等健康与否,以及获取其相应状态;
(2) 管理集群、节点、索引及元数据;
(3) 执行CRUD(增删查改)操作;
(4) 执行高级操作,例如paging, filtering等;
ES访问接口:9200/tcp
curl -X<VERB> '<PROTOCOL>://HOST:PORT/<PATH>?<QUERY_STRING>' -d '<BODY>'
#注释:
<VERB>:请求方法,如get、put、delete
<PROTOCOL>:协议http、https
<QUERY_STRING>:查询字符串,例如?pretty表示用JSON格式输出;
<BODY>:json格式的请求主体
例:curl -X GET 'http://192.168.31.144:9200/?preey'
_cat API:
curl -X GET 'http://192.168.31.144:9200/_cat/' #用catAPI显示易读的输出结果;?help表示帮助
curl -X GET 'http://192.168.31.144:9200/_cat/nodes?help' #?help表示nodes选项的帮助
Cluster APIs:
health:
curl -XGET 'http://172.16.100.67:9200/_cluster/health?pretty'
state:
curl -XGET 'http://172.16.100.67:9200/_cluster/state/<metrics>?pretty' #查看集群状态;<metrics>:方法
stats:统计数据
集群数据
curl -XGET 'http://172.16.100.67:9200/_cluster/stats'
节点数据:
curl -XGET 'http://172.16.100.67:9200/_nodes/stats'
Plugins:
插件扩展ES的功能:
添加自定义的映射类型、自定义分析器、本地脚本、自定义发现方式;
安装:
直接将插件放置于plugins目录中即可;
目录:/usr/share/elasticsearch/plugins
使用plugin脚本进行安装;
/usr/share/elasticsearch/bin/plugin -h
-l
-i, --install
-r, --remove
站点插件:
http://HOST:9200/_plugin/plugin_name
CRUD操作相关的API:
创建文档:
注意:引用的索引或类型不存在时会自动创建,id相同时会自动替换
curl -XPUT 'localhost:9200/students/class1/2?pretty' -d '
{
"first_name": "Rong",
"last_name": "Huang",
"gender": "Female",
"age": 23,
"courses": "Luoying Shenjian"
}'
获取文档:
~]# curl -XGET 'localhost:9200/students/class1/2?pretty'
{
"_index" : "students",
"_type" : "class1",
"_id" : "2",
"_version" : 1,
"found" : true,
"_source":
{
"first_name": "Rong",
"last_name": "Huang",
"gender": "Female",
"age": 23,
"courses": "Luoying Shenjian"
}
}'
更新文档:
PUT方法会覆盖原有文档;
如果只更新部分内容,得使用_update API
~]# curl -XPOST 'localhost:9200/students/class1/2/_update?pretty' -d '
{
"doc": { "age": 22 }
}'
删除文档:
DETELE
~]# curl -XDELETE 'localhost:9200/students/class1/2'
删除索引:
~]# curl -XDELETE 'localhost:9200/students'
~]# curl -XGET 'localhost:9200/_cat/indices?v' #验证查看当前的索引有哪些
查询数据:
Query API
Query DSL:基于json的用于构建复杂查询的语言
用户实现诸多类型的查询操作,比如,simple term query, phrase, range boolean, fuzzy等;
ES的查询操作执行分为两个阶段:
分散阶段:把整个查询操作分散到shared所在的节点上去
合并阶段:
查询方式:
向ES发起查询请求的方式有两种:
1、通过Restful request API查询,也称为query string;
~]# curl -XGET 'localhost:9200/students/_search?pretty' #查询所有
2、通过发送REST request body进行;
~]# curl -XGET 'localhost:9200/students/_search?pretty' -d '
> {
> "query": { "match_all": {} } #查询所有
> }'
实例:
[root@node1 ~]# curl -XGET 'localhost:9200/students/_search?pretty' #查询students索引的所有内容
{
"took" : 25, #执行时常,单位毫秒
"timed_out" : false, #是否超时
"_shards" : {
"total" : 5, #涉及到几个分片
"successful" : 5, #成功几个
"failed" : 0 #失败几个
},
"hits" : { #命中
"total" : 1, #命中的文档一共有几个
"max_score" : 1.0, #最高的命中的分数
"hits" : [ { #以数组形式表示
"_index" : "students",
"_type" : "class1",
"_id" : "2", #查询id
"_score" : 1.0, #评分。加权值
"_source": #元数据
{
"first_name": "Rong",
"last_name": "Huang",
"gender": "Female",
"age": 23,
"courses": "Luoying Shenjian"
}
} ]
}
}
} ]
}
}
多索引、多类型查询:
curl -XGET 'localhost:9200/_search:所有索引;
curl -XGET 'localhost:9200/INDEX_NAME/_search:单索引;
curl -XGET 'localhost:9200/INDEX1,INDEX2/_search:多索引;
curl -XGET 'localhost:9200/s*,t*/_search:通配符多索引查询
curl -XGET 'localhost:9200/students/class1/_search:单类型搜索
curl -XGET 'localhost:9200/students/class1,class2/_search:多类型搜索
Mapping和Analysis:
ES:对每一个文档,会取得其所有域的所有值,生成一个名为“_all”的域;执行查询时,如果在query_string未指定查询的域,则在_all域上执行查询操作,如果指定域会做更精确匹配;
(前两个:表示在_all域搜索;后两个:在指定的域上搜索;)
GET /_search?q='Xianglong'
GET /_search?q='Xianglong%20Shiba%20Zhang' #%20表示空格
GET /_search?q=courses:'Xianglong%20Shiba%20Zhang'
GET /_search?q=courses:'Xianglong'
Mapping:主要作用是定义了一个文档中域中的数据类型是如何被解析的
数据类型:string, numbers, boolean, dates
查看指定类型的mapping示例:
~]# curl 'localhost:9200/students/_mapping/class1?pretty'
ES中搜索的数据广义上可被理解为两类:
types:exact #指定类型的精确值
full-text #全文搜索
精确值:指未经加工的原始值;在搜索时进行精确匹配;
full-text:用于引用文本中数据;判断文档在多大程序上匹配查询请求;即评估文档与用户请求查询的相关度,进行多大成都的模糊匹配;
为了完成full-text搜索,ES必须首先分析文本,并创建出倒排索引;倒排索引中的数据还需进行“正规化”为标准格式;
分词
正规化 #例如全部小写
分析:就是分词加正规化过程
分析需要由分析器进行:analyzer
分析器由三个组件构成:字符过滤器、分词器、分词过滤器
ES内置的分析器:
Standard analyzer:标准分分析器是ES的默认分析器
Simple analyzer
Whitespace analyzer
Language analyzer
分析器不仅在创建索引时用到;在构建查询时也会用到;这两者的分析器要保持一致,不然匹配度不高
Query DSL:
request body:
分成两类:
query dsl:执行full-text查询时,基于相关度来评判其匹配结果;
查询执行过程复杂,且不会被缓存;
filter dsl:执行exact查询时,基于其结果为“yes”或“no”进行评判,精确匹配;
速度快,且结果缓存;
查询语句的结构:
{
QUERY_NAME: {
AGGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,...
}
}
}
filter dsl:
term filter:精确匹配包含指定term的文档;
{ "term": {"name": "Guo"} }
curl -XGET 'localhost:9200/students/_search?pretty' -d {
"query": {
"term": {
"name": "Guo"
}
}
}
terms filter:用于多值精确匹配;
{ "terms": { "name": ["Guo", "Rong"] }}
range filters:用于在指定的范围内查找数值或时间。
{ "range":
"age": {
"gte": 15,
"lte": 25
}
}
gt, lt, gte, lte
exists and missing filters:用于字段存在与否检索
{
"exists": {
"age": 25
}
}
boolean filter:
基于boolean的逻辑来合并多个filter子句;
must:其内部所有的子句条件必须同时匹配,即and;
must: {
"term": { "age": 25 }
"term": { "gender": "Female" }
}
must_not:其所有子句必须不匹配,即not
must_not: {
"term": { "age": 25 }
}
should:至少有一个子句匹配,即or
should: {
"term": { "age": 25 }
"term": { "gender": "Female" }
}
QUERY DSL:
match_all Query:
用于匹配所有文档,没有指定任何query,默认即为match_all query.
{ "match_all": {} }
match Query:
在几乎可以任何域上执行full-text或exact-value查询;
如果执行full-text查询:首先对查询时的语句做分析;
{ "match": {"students": "Guo" }} #在students这张表中查询
如果执行exact-value查询:搜索精确值;此时,建议使用过滤,而非查询;
{ "match": {"name": "Guo"} } #精确查询域为name值为Guo的数据
multi_match Query:
用于在多个域上执行相同的查询;
{
"multi_match":
"query": full-text search #执行此查询
"field": {'field1', 'field2'} #同时在field1、field2两个域上
}
示例:
{
"multi_match":
"query": {
"students": "Guo"
}
"field":
{
"name",
"description"
}
}
bool query:
基于boolean逻辑合并多个查询语句;与bool filter不同的是,查询子句不是返回"yes"或"no"的精准匹配,而是其计算出的匹配度分值。因此,boolean Query会为各子句合并其score;并计算匹配都的值是must或must not或should
must:
must_not:
should:
合并filter和query:可以把filter嵌入到query中
{
"filterd": {
query: { "match": {"gender": "Female"} }
filter: { "term": {"age": 25}}
}
}
查询语句语法检查:
GET /INDEX/_validate/query?pretty
{
...
}
GET /INDEX/_validate/query?explain&pretty #显示错误信息
{
...
}