须要明白的问题
什么是倒排索引?它的组成是什么?node
常见的相关性算分方法有哪些?linux
为何查询语句没有返回预期的文档?git
经常使用的数据类型有哪些?Text和Keyword的区别是什么?es6
集群是如何搭建起来的?是如何实现故障转移的?github
Shard具体是由什么组成的?json
Elastic Stack
构建在开源基础之上, Elastic Stack 让您可以安全可靠地获取任何来源、任何格式的数据,而且可以实时地对数据进行搜索、分析和可视化浏览器
Elasticsearch 是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可用和管理便捷性而设计。安全
Kibana 可以以图表的形式呈现数据,而且具备可扩展的用户界面,供您全方位配置和管理 Elastic Stack。微信
Logstash 是动态数据收集管道,拥有可扩展的插件生态系统,可以与 Elasticsearch 产生强大的协同做用。数据结构
Beats 是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。
基础概念
文档 Document :用户存储在ES中的数据文档
索引 Index :由具备一些相同字段的文档的集合
类型 Type : 容许将不一样类型的文档存储在同一索引中,6.0开始官方不容许在一个index下创建多个type,统一type名称:doc
节点 Node :一个Elasticsearch的运行实例,是集群的构成单元,存储部分或所有数据,并参与集群的索引和搜索功能
集群 Cluster :由一个或多个节点组成的集合,共同保存全部的数据,对外提供服务(包括跨全部节点的联合索引和搜索功能等)
分片 Shards :分片是为了解决存储大规模数据的问题,将数据切分分别存储到不一样的分片中
副本 Replicas :副本能够在分片或节点发生故障时提升可用性,并且因为能够在全部副本上进行并行搜索,因此也能够提升集群的吞吐量
近实时 Near Realtime(NRT):从索引文档到可搜索文档的时间有一点延迟(一般为一秒)
note:
在建立索引的时候若是没有配置索引Mapping,一个索引默认有5个shard和1个副本,一个索引总共有10个shard(算上副本shard)
Elasticsearch 的shard其实是一个Lucene索引,截止Lucene-5843,一个Lucene索引限制的最大文档数为2,147,483,519 (= Integer.MAX_VALUE - 128)
安装Elasticsearch & Kibana
ES和Kibana的安装很简单,前提须要先安装好Java8,而后执行如下命令便可
elasticsearch单节点最简安装
# 在Ubuntu16.04上安装,方式有不少种,选择二进制压缩包的方式安装
# 1. 在普通用户家目录下,下载压缩包
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.tar.gz
# 2. 解压
tar -xvf elasticsearch-6.3.2.tar.gz
# 3. 移动至/opt目录下
sudo mv elasticsearch-6.3.2 /opt
# 4. 修改配置文件elasticsearch.yml中的 network.host 值为 0.0.0.0,其余的配置参考官方文档
cd /opt/elasticsearch-6.3.2vi config/elasticsearch.yml
# 5. 启动单节点,而后浏览器访问host:9200便可看到ES集群信息
bin/elasticsearch
kibana最简安装
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.3.2-linux-x86_64.tar.gz
shasum -a 512 kibana-6.3.2-linux-x86_64.tar.gz
tar -xzf kibana-6.3.2-linux-x86_64.tar.gz
sudo mv kibana-6.3.2-linux-x86_64 /optcd /opt/kibana-6.3.2-linux-x86_64
# 修改 config/kibana.yml中 server.host: 0.0.0.0# 启动Kibana,访问 host:5601便可进入kibana界面
交互方式 Rest API
Elasticsearch集群对外提供RESTful API
Curl命令行
Kibana Devtools
Java API
其余各类API,如Python API等
note: 咱们后面主要使用 Kibana Devtools 这种交互方式
数据类型
字符串: text(分词), keyword(不分词)
数值型: long, integer, byte, double, float, half_float, scaled_float
布尔: boolean
日期: date
二进制: binary
范围类型: integer_range, float_range, long_range, double_range, date_range
复杂数据类型: Array, Object, Nested
地理: geo_point, geo_shape
专业: ip,completion, token_count, murmur3, Percolator, join
组合的
探索ES集群
使用_cat API探索集群的健康状况
GET /_cat/health?v# 结果epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent1534319381 15:49:41 elasticsearch green 3 3 118 59 0 0 0 0 - 100.0%
集群的健康状态(status)有三种:
green:一切正常(集群功能齐全)
yellow:全部数据均可用,但存在一些副本未分配(群集功能齐全)
red:一些数据因为某种缘由不可用(群集部分功能失效)
查看节点信息
GET /_cat/nodes?v
# 结果(个人ES集群安装了三个节点)ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name10.100.97.207 30 96 13 0.15 0.08 0.08 mdi * master10.100.97.246 68 96 3 0.00 0.00 0.00 mdi - hadoop210.100.98.22 15 97 2 0.00 0.02 0.04 mdi - hadoop3
查看索引信息
GET /_cat/indices?v
# 结果health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open logstash-2015.05.20 4BjPjpq6RhOSCNUPMsY0MQ 5 1 4750 0 46.8mb 24.5mb
green open logstash-2015.05.18 mDkUKHSWR0a8UeZlKzts8Q 5 1 4631 0 45.6mb 23.8mb
green open hockey g1omiazvRSOE117w_uy_wA 5 1 11 0 45.3kb 22.6kb
green open .kibana AGdo8im_TxC04ARexUxqxw 1 1 143 10 665.6kb 332.8kb
green open shakespeare 5009bDa7T16f5qTeyOdTlw 5 1 111396 0 43.9mb 22mb
green open logstash-2015.05.19 az4Jen4nT7-J9yRYpZ0A9A 5 1 4624 0 44.7mb 23.1mb
...
操做数据
插入文档并查询
# 插入一个文档PUT /customer/_doc/1?pretty
{ "name": "John Doe"}# 结果{ "_index": "customer", "_type": "_doc", "_id": "1", "_version": 1, "result": "updated", "_shards": { "total": 2, "successful": 2, "failed": 0
}, "_seq_no": 1, "_primary_term": 1}# 查询该文档GET /customer/_doc/1#结果{ "_index": "customer", "_type": "_doc", "_id": "1", "_version": 1, "found": true, "_source": { "name": "John Doe"
}
}
note:
customer
为索引名,_doc
为type,1为文档_id,须要注意的是:在es6.x建议索引的type值固定为_doc
,在以后的版本将删除type了;文档id若不指定,es会自动分配一个_id给文档插入文档后,查看索引信息
GET /_cat/indices?v
能够看到多了 customer 的索引信息文档结果,_source字段是原始的json内容,其余的为文档元数据
文档元数据
用于标注文档的元信息
_index: 文档所在的索引名
_type: 文档所在的类型名
_id: 文档的惟一id
_uid: 组合id,由_type和_id组成(6.0开始_type再也不起做用,同_id同样)
_source: 文档的原始json数据,能够从这里获取每一个字段的内容
_all: 整合全部字段内容到该字段,默认禁用
_routing 默认值为 _id,决定文档存储在哪一个shard上:
shard_num = hash(_routing) % num_primary_shards
删除索引
DELETE customer#结果{ "acknowledged": true}GET /_cat/indices?v# 再次查看索引信息,能够发现 customer 不存在,已被删除
更新文档
PUT /customer/_doc/1?pretty{ "name": "John Doe"}
POST /customer/_doc/1/_update{ "doc": { "name": "Jane Doe" }
}
POST /customer/_doc/1/_update{ "doc": { "name": "Jane Doe", "age": 20 }
}# 能够看到 \_version的值一直在增长
删除文档
DELETE /customer/_doc/2
批量操做
es提供了_bulk API供批量操做,能够提升索引、更新、删除等操做的效率
_bulk操做的类型有四种:
index 索引:若已存在,则覆盖,文档不存在则建立
create 建立:文档不存在则异常
delete 删除
update 更新
# _bulk 任务:# 1. index建立 customer索引下id为3的文档# 2. delete删除 customer索引下id为3的文档# 3. create建立 customer索引下id为3的文档# 4. update更新 customer索引下id为3的文档POST _bulk
{"index":{"_index":"customer","_type":"_doc","_id":"3"}}
{"name":"whirly"}
{"delete":{"_index":"customer","_type":"_doc","_id":"3"}}
{"create":{"_index":"customer","_type":"_doc","_id":"3"}}
{"name":"whirly2"}
{"update":{"_index":"customer","_type":"_doc","_id":"3"}}
{"doc":{"name":"whirly3"}}
note:
批量查询用的是 Multi Get API
探索数据
一个简单的数据集,数据结构以下:
{ "account_number": 0, "balance": 16623, "firstname": "Bradshaw", "lastname": "Mckenzie", "age": 29, "gender": "F", "address": "244 Columbus Place", "employer": "Euron", "email": "bradshawmckenzie@euron.com", "city": "Hobucken", "state": "CO"}
导入这个简单的数据集到es中
# 下载wget https://raw.githubusercontent.com/elastic/elasticsearch/master/docs/src/test/resources/accounts.json# 导入curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_doc/_bulk?pretty&refresh" --data-binary "@accounts.json"
上述命令是经过 _bulk API 将 account.json 的内容插入 bank 索引中,type 为 _doc
# account.json的内容:{"index":{"_id":"1"}}
{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}...# 导入完成后能够看到 bank 索引已存在 1000 条数据GET bank/_search
查询数据 API
任务:查询全部数据,根据 account_number 字段升序排序
URI Search 方式
GET /bank/_search?q=*&sort=account_number:asc&pretty
Request Body Search 方式
GET /bank/_search
{ "query": { "match_all": {} }, "sort": [
{ "account_number": "asc" }
]
}
结果
{ "took": 41, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0
}, "hits": { "total": 1000, "max_score": null, "hits": [
{ "_index": "bank", "_type": "account", "_id": "0", "_score": null, "_source": { "account_number": 0, "balance": 16623, "firstname": "Bradshaw", "lastname": "Mckenzie", "age": 29, "gender": "F", "address": "244 Columbus Place", "employer": "Euron", "email": "bradshawmckenzie@euron.com", "city": "Hobucken", "state": "CO"
}, "sort": [ 0
]
}...
]
}
}
各个参数意思:
took:本次查询耗费的时间(单位:毫秒)
timed_out:是否超时
_shards:本次查询搜索的 shard 的数量,包括成功的和失败的
hits:查询结果
hits.total:匹配的文档数量
hits.hits:匹配的文档,默认返回10个文档
hits.sort:排序的值
_score:文档的得分
hits.max_score:全部文档最高的得分
简要介绍 Query DSL
这个Elasticsearch提供的基于 json 的查询语言,咱们经过一个小任务来了解一下
任务要求:
查询 firstname 中为 "R" 开头,年龄在 20 到 30 岁之间的人物信息
限制返回的字段为 firstname,city,address,email,balance
根据年龄倒序排序,返回前十条数据
对 firstname 字段进行高亮显示
同时求全部匹配人物的 平均balance
GET bank/_search
{ "query": { "bool": { "must": [
{ "match_phrase_prefix": { "firstname": "R"
}
}
], "filter": { "range": { "age": { "gte": 20, "lte": 30
}
}
}
}
}, "from": 0, "size": 10, "sort": [
{ "age": { "order": "desc"
}
}
], "_source": [ "firstname", "city", "address", "email", "balance"
], "highlight": { "fields": { "firstname": {}
}
}, "aggs": { "avg_age": { "avg": { "field": "balance"
}
}
}
}
其中:
query 部分能够写各类查询条件
from, size 设置要返回的文档的起始序号
sort 设置排序规则
_source 设置要返回的文档的字段
highlight 设置高亮的字段
aggs 为设置聚合统计规则
更多查询示例
match_all 查询 bank 索引全部文档
GET /bank/_search
{ "query": { "match_all": {}
}, "size": 2}
match 全文搜索,查询 address 字段值为 mill lane 的全部文档
GET /bank/_search
{ "query": { "match": { "address": "mill lane"
}
}
}
match_phrase 短语匹配
GET /bank/_search
{ "query": { "match_phrase": { "address": "mill lane"
}
}
}
note: match 和 match_phrase 的区别:
match 中会分词,将 mill lane 拆分为 mill 和 lane, 实际查询 address 中有 mill 或者 lane 的文档
match_phrase:将 mill lane 做为一个总体查询,实际查询 address 中有 mill lane 的文档
布尔查询(多条件查询)
GET /bank/_search
{ "query": { "bool": { "must": [
{ "match": { "age": "40" } }
], "must_not": [
{ "match": { "state": "ID" } }
]
}
}
}
布尔查询-过滤 查询 bank 索引中 balance 值在 20000 到 30000 之间的文档
GET /bank/_search
{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000
}
}
}
}
}
}
聚合查询 对全部文档进行聚合,state 值相同的分到同一个桶里,分桶结果命名为 group_by_state ,再对每一个桶里的文档的 balance 字段求平均值,结果命名为 average_balance,经过设置 size 的值为0,不返回任何文档内容
GET /bank/_search
{ "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword"
}, "aggs": { "average_balance": { "avg": { "field": "balance"
}
}
}
}
}
}
分别计算 age 值在 20~30 ,3040,4050 三个年龄段的男和女的平均存款balance
GET /bank/_search
{ "size": 0, "aggs": { "group_by_age": { "range": { "field": "age", "ranges": [
{ "from": 20, "to": 30
},
{ "from": 30, "to": 40
},
{ "from": 40, "to": 50
}
]
}, "aggs": { "group_by_gender": { "terms": { "field": "gender.keyword"
}, "aggs": { "average_balance": { "avg": { "field": "balance"
}
}
}
}
}
}
}
}
更多内容请访问个人我的博客:http://laijianfeng.org
参考文档:
elasticsearch 官方文档 Getting Started
慕课网 Elastic Stack从入门到实践
本文分享自微信公众号 - 小旋锋(whirlysBigData)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。