ElasticSearch的基本组件:
索引(Index): 文档容器,索引是具有类似属性的文档的集合。类似于关系型的表,索引名不需使用小写字符。
类型(type): 类型是索引内部的逻辑分区,其意义完全取决于用户需求。一个索引内部可定义一个或多个类型,相当于关系型表结构。
文档(document): 文档是Lucence索引和搜索的原子单位,它包含了一个或多个域。是域的容器;基于JSON格式表示。每个域的组成部分: 一个名字,一个或多个值;拥有多个值的域,通常称为多值域。
映射(mapping): 原始内容存储为文档之前需要事先进行分析(分词);映射用于定义此分析机制该如何实现,分析包括切词、过滤等。此外,ES还为了mapping提供了其他功能,例如:域中内容排序等。
ElasticSearch的集群组件:
Cluster: ES的集群标识为进群名称,默认为elasticsearch。节点就是靠此名字决定加入那个集群中(一个节点只能属于一个集群)
Node:运行了单个ES实例的主机即为节点。用于存储数据、参与集群索引及搜索操作。节点的标识依赖节点名,节点ID默认会随机生成
Shard: 将索引切割成为的物理存储组件,每个Shard都是一个完整的、独立的索引。创建索引时,ES默认将其分割为5个shard,用户也可以按需自定义。
Shard分为两种类型:primary shard 和 replica(primary shard的副本)
primary shard:
每个索引对ES讲都会被切成5个primary shard,按理每个primary都应该有 replica
但是可以为多个,每个索引创建后shard不能更改
replica:
Replica可以用于冗余,也可以作为读的负载均衡
副本可以动态修改数量
ElasticSearch集群的工作过程:
启动时,通过多播(默认)或单播方式在9300/tcp查找同一集群中的其他节点,并与之建利通讯。
集群中的所有节点会选举出一个主节点负责管理整个集群状态,以及在集群范围内决定各shards的分布方式,站在用户角度而言每个节点都可以响应用户所有请求,用户无需确认哪个是主节点。
必要时如果有节点宕机,主节点会根据集群状态修复,并确认所有可用的shards和主shards。
集群状态:green(正常),red(不可用),yellow(修复)。
在yellow状态下所有shard都属于未分配shard,副本不可用,只能使用主的;如果宕机的是主shard则replica称为主shard。
yellow状态下吞吐能力有限,如果某个shard副本少于配额,会自动补充。
周期性检查各节点的健康状态,修复后rebalance各节点。
如果primary shard宕机,而有多个replica,由选举过程决定谁成为primary shard。
当然也可以手动指定Master节点,就像我们部署的那样。
ElasticSearch提供了一个Restful风格的API
ES API的类型:
1、检查集群、节点、索引等健康与否,以及获取其相应状态。
2、管理集群、节点、索引及元数据。
3、执行CRUD操作(增删查改)。
4、执行高级操作,例如paging,filtering等。
格式:
curl -X<http_action(get/put/post/delete)> 'http(s)://HOST:PORT/<PATH>?<QUERY_STRING>' -d '<BODY>'
QUERY_STRING: 查询参数,例如?pretty表示易读的json格式输出
BODY: 请求的主题
curl -X GET '192.168.2.130:9200/?pretty' #查看单个节点的信息,由于curl方式默认就是GET 所以可以写成curl 192.168.2.130:9200/?pretty
cat 查看集群API,API都用_xxx的方式表示,下划线
curl -X GET 'http://192.168.2.130:9200/_cat' #列出所有cat方法
curl -X GET 'http://192.168.2.130:9200/_cat/nodes?v' #查看节点信息,?v 代表详细格式(可不加)
curl -X GET 'http://192.168.2.130:9200/_cat/nodes?help' #获取node可查询相关帮助
curl -X GET 'http://192.168.2.130:9200/_cat/nodes?h=name,ip,port,uptime,heap.current' #查询节点部分信息,关键字可以在上行帮助里找到
curl -X GET 'http://192.168.2.131:9200/_cat/master?v' #查看主节点信息,可以从其他节点查询
curl -X GET 'http://192.168.2.130:9200/_cat/health?v' #查看集群健康状态
如果不方便登入ES主机操作,也可以登入Kibana或者ElasticHQ进行操作
集群 APIs _cluster
curl -X GET 'http://192.168.2.130:9200/_cluster/health?pretty' #获取集群健康信息
curl -X GET 'http://192.168.2.130:9200/_cluster/health/nginx-test-2019.10.14,nginx-test-2019.10.16' #获取索引健康信息
curl -X GET 'http://192.168.2.130:9200/_cluster/health?level=shards&pretty' #查看索引shard信息
CURD(增删查改)索引管理 APIs
-H "Content-Type: application/json" -- 由于新版本的ElasticSearch新增了安全机制,不加肯能会报错,出现 "
"error" : "Content-Type header [application/x-www-form-urlencoded] is not supported",
"status" : 406
"的报错,当然以前的版本也需要只不过以前不强求用户要加入此header头。
Why are we changing this?
We know that the content-type sniffing has been quite convenient when using basic HTTP tools such as curl. Many of us are quite accustomed to searching a cluster by running something like this:
知识兔curl 'http://localhost:9200/_search' -d' { "query" : { "match_all" : {} } }'
But, we need to make that sort of operation slightly more verbose, and include the content-type, in the interests of clarity and security.
新增文档,payroll的索引和devops的类型会自动创建
curl -H "Content-Type: application/json" -XPUT '192.168.2.130:9200/payroll/devops/1?pretty' -d '{
"name": "Alice",
"sex": "F",
"job": "UI",
"salary": "10000",
"performance": "2000",
"tax": "-1900",
"payment": "10100"
}'
curl -H "Content-Type: application/json" -XPUT '192.168.2.130:9200/payroll/devops/2?pretty' -d '{
"name": "Tom",
"sex": "M",
"job": "UI",
"salary": "10000",
"performance": "2000",
"tax": "-1900",
"payment": "10100"
}'
curl -H "Content-Type: application/json" -XPUT '192.168.2.130:9200/payroll/devops/3?pretty' -d '{
"name": "Gaemon",
"sex": "F",
"job": "UI Manager",
"salary": "18000",
"performance": "5000",
"tax": "3200",
"payment": "19800"
}'
获取文档信息
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/2?pretty'
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/3?pretty'
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/_search?q="Alice"' #查询某个域与条件匹配的数据
更新文档,ES中更新文档有两种方式:
1、使用PUT直接覆盖,相同的index、type和id 就会覆盖替换
2、_update APIs
curl -H "Content-Type: application/json" -XPOST '192.168.2.130:9200/payroll/devops/1/_update?pretty' -d '
{
"doc": { "job": "JAVA" }
}'
{
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/1?pretty'
{
"_index" : "payroll",
"_type" : "devops",
"_id" : "1",
"_version" : 3,
"_seq_no" : 4,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "Alice",
"sex" : "F",
"job" : "JAVA",
"salary" : "10000",
"performance" : "2000",
"tax" : "-1900",
"payment" : "10100"
}
}
删除文档
curl -H "Content-Type: application/json" -XDELETE '192.168.2.130:9200/payroll/devops/1'
删除索引
curl -H "Content-Type: application/json" -X GET '192.168.2.130:9200/_cat/indices?v' #先查询现有文档
curl -H "Content-Type: application/json" -XDELETE '192.168.2.130:9200/nginx-test-2019.10.14'
查询数据,采用域查询语言(Query DSL)基于json
可以实现诸多类型的查询操作,比如simple term query, range,boolean,fuzzy等,可以逻辑组合查询。
ES的查询分为两个阶段:
分散到shard所在节点-如果被查询的shard不在本地,需要转发查询。
合并所有shard返回的结果。
查询方式也有两种:
1、通过Restfull request API查询,也称为query string
#查询索引所有文档
curl -XGET 'localhost:9200/students/_search?pretty'
#hits 为命中的文档,里面的id为文档id
2、通过发送REST request body 进行
#query body 可以更为详细的写查询
curl -XGET 'localhost:9200/students/_search?pretty' -d '
{
"query": { "match_all": {} }
}' #mathc_all 查询所有
多索引、多类型查询
查询所有索引
curl -XGET '192.168.2.130:9200/_search?pretty'
多索引查询
curl -XGET '192.168.2.130:9200/INDEX1,INDEX2,INDEX3/_search?pretty'
使用通配符多索引查询,s开头和t开头的索引
curl -XGET '192.168.2.130:9200/d*,n*/_search?pretty'
多类型查询
curl -XGET '192.168.2.130:9200/payroll/devops,hr/_search?pretty' #如果有hr这个类型
Mapping和Analysis:
ES对每一个文档会取得其所有域的所有值,生成一个名为"_all"的域;执行查询时,如果query_string未指定域,则在_all域上执行查询操作。
全域搜索 (_al)
curl -H "Content Type: application/json" -XGET '192.168.2.130:9200/_search?q='10000'' #查询所有域中与条件相等的值,并列出此文档全部数据
#如果涉及到空格,可以用%20来代替
指定域搜索,做精确匹配
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/_search?q=job:"UI"' #只对job做查询,当然他也属于模糊查询,job中有UI的都会查出来
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/_search?q=job:"UI%20Manager"' #空格用%20代替,如果不行则复制到浏览器中使用空格表示,浏览器会自动转换
查询index中的doc字段信息
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_mapping?pretty'
ES中搜索的数据广义上可被理解为两类:
1、types:exact #指定类型上做精确搜索
精确值:指未经加工的原始值,精确匹配
2、full-text
全文搜索时用于引用文本中的数据,不区分大小写,可能还有近义词,模糊匹配,查询相关度
为了完成full-text搜索,ES必须先分析文本,并创建倒排索引,还需要进行"正规化"标准格式,多为小写、近义词替换修改
分析(分析器) analyzer
分词
正规化
构建倒排索引
分析器三个组件构成:
字符过滤器 (过滤、不需要分词字符、html标签等)
分词器
分词过滤器 (过滤助词)
ES内置的分析器:
standard analyzer #ES默认的,根据Unicode标准进行分词,中文也是可以的
simple analyzer#简单分析器,非字母作为单词边境
whitespace analyzer #空白字符分析器,空白最为单词边境
Language analyzer #语言分析器,适用于多语言的
分析器不仅是创建索引是用到;在构建查询时也会用到
对查询 去除html标签、切词、正规化
搜索和查询时要选择保证结果一致的分析器
ES Query DSL 深入
request body:
分成两类:
query dsl
需要根据查询条件的相关度选择query_dsl,执行full-text查询时评判匹配程度
查询过程复杂,不能缓存结果
filter dsl
精确值查询,匹配或不匹配,执行exact查询时,基于结果"yes"或"no"评判
执行速度块快,适用于缓存,结果可缓存
查询语句结构:
{
Query_name:{
ARGUMENT: VALUE,
ARGUMENT: VALUE,
...
}
{
Query_name:{
FIELD_NAME:{
ARGUMENT: VALUE
}
}
filter dsl:
term filter:
精确匹配包含指定项的文档
UI Manager #UI可以视为一项,Manager也可以视为一项,UI%20Manager也是一项
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"term": {"job": "UI"}
}
}'
你会发现当你在匹配UI时结果为空,这是因为标准分词器,是将字段内容以小写方式记录,并倒排索引,term精确匹配是区分大小写的。
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"term": {"job": "ui"}
}
}'
现在得到了你想要的结果。
查询全部内容
curl -H "Content-Type: application/json" -XGET "192.168.2.130:9200/payroll/_search?pretty" -d'
{
"query":
{
"match_all":{}
}
}'
多项精确匹配
curl -H "Content-Type: application/json" -XGET '192.16 8.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"terms": { "name": ["alice","tom"] }
}
}'
范围精确查询,当初salary值给的是字符格式,不是数值所以无法比较,这个只是示例
curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"range": {"salary": "gte":8000,"lte":25000}
}
}'
判断是否存在
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"}
}
full-text、exact-value查询
match_all Query:
用于匹配所有文档,没有指定任何query,默认即为match_all
{ "match_all": {} }
match Query:
几乎在任何域上执行full-text或exact-value查询
如果执行full-text查询: 首先对查询时的语句做分析:
{ "match": {"students": "Guo"} }
如果执行exact-value查询:搜索精确值,此时,建议使用过滤,而非查询
{ "match": {"name": "Guo"} }
multi_match Query:
用于在多个域上执行相同的查询:
{
"multi_match":
"query": full-text search
"field": {'field1','field2'}
}
{
"multi_match":
"query": {
"students": "Guo"
}
"field": {
"name",
"description"
}
}
可以合并filter和query一起使用
组合查询
{
"filterd": {
query: { "match": {"gender": "Female"} }
filter: { "term": {"age":25} }
}
}
查询语句语法检查:
返回对错
GET /$index/_validate/query?pretty
{
$query_body
}
返回错误详情
GET /$index/_validate/query?explain&pretty
{
$query_body
}