Elasticsearch
Elasticsearch
Elasticsearch是基于Lucene的全文检索技术,基于倒排索引,采用Rest风格API。
默认端口:9200用于http连接; 9300用于tcp连接
注意:安装需要保证elasticsearch、kibana、analysis_ik版本一致。
elasticsearch-head
es的管理界面,安装相关chrome拓展使用
项目地址:https://github.com/mobz/elasticsearch-head
Kibana
Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等。默认端口5601。
IK Analysis
项目地址: https://github.com/medcl/elasticsearch-analysis-ik
- Analyzer:
ik_smart
, ik_max_word
- 测试安装结果: 打开kibana控制台,输入如下请求,若成功分词则成功安装
1 2 3 4 5
| POST _analyze { "analyzer": "ik_smart", "text": "我是中国人" }
|
操作索引indices
相关概念
- 索引库(indices)
- 类型(type): 7.x已经移出这个概念,使用_doc兼容
- 映射配置(mappings):字段的数据类型、属性、是否索引、是否存储等特性
- 文档(document)
- 字段(field)
一些集群相关的概念:
- 集群(cluster)
- 节点(node)
- 索引集(Indices,index的复数):逻辑上的完整索引
- 分片(shard):数据拆分后的各个部分
- 副本(replica):每个分片的复制
创建索引
1 2 3 4 5 6 7 8 9 10 11
| PUT index { "settings": { # 分片数,副本数 "number_of_shards": 3, "number_of_replicas": 2 }, # 映射配置 "mappings": { } }
|
查看索引
删除索引
映射配置
elasticsearch7.x中移除了类型(Type)这个概念,要使用_doc占位。
1 2 3 4 5 6 7 8 9 10 11
| PUT /索引库名/_mapping/类型名称 { "properties": { "字段名": { "type": "类型", # 可以是text、long、short、date、integer、object等 "index": true, # 是否索引 "store": true, # 是否存储 "analyzer": "分词器" } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| PUT index/_mapping/_doc { "properties": { "title": { "type": "text", "analyzer": "ik_max_word" }, "images": { "type": "keyword", "index": "false" }, "price": { "type": "float" } } }
|
字段属性
type: 字段类型
String类型,又分两种:
- text:可分词,不可参与聚合
- keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合
Numerical:数值类型,分两类
- 基本数据类型:long、interger、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float
- 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
Date:日期类型
- elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
index: 是否索引
store:是否将数据进行额外存储
- 默认为false,不进行额外存储
- es在创建索引时,会将文档所有数据保存到
_source
。因此,不论store为何值都可以搜到结果。
boost:激励因子
操作文档document
新增文档
1 2 3 4 5
| POST/PUT /index/_doc/id可写可不写 { "title":"小米手机" "price":2699.00 }
|
1 2 3 4 5
| POST /index/_doc/_bulk { "index":{} } { "title":"OnePlus8","price":3999 } { "index":{} } { "title":"OnePlus8 pro","price":4999 }
|
修改文档
1 2 3 4 5
| PUT /index/_doc/3 { "title":"超大米手机" "price":3899.00 }
|
1 2 3 4 5 6 7 8 9 10
| POST goods/_update_by_query { "script": { "inline": "ctx._source.price = params.price", "params": { "state": 9999 } }, "query": {"match_all": {}} }
|
删除文档
1 2 3 4
| POST goods/_delete_by_query { "query": {"match_all": {}} }
|
查看文档
查询
基本语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| GET /索引库名/_search { # 查询 "query":{ "查询类型":{ "查询条件":"查询条件值" } } # 设置要显示的字段 "_source": ["field", ...], # 排序 "sort": [{"field": {"order": "desc|asc"}}, ...], # 分页 "from": 从第几个开始 "size": 每页显示几个 }
// or GET index/type/_id GET index/_search?field=value
|
查询query
- 查询类型:
match_all
, match
,term
, range
等等
- 查询条件:文档field
_source设置要显示的field
sort排序
1 2 3 4
| "sort": [ {"price": {"order": "desc"}}, {"_score": {"order": "desc"}} ]
|
match_all查询所有
1 2 3 4 5 6
| GET index/_search { "query":{ "match_all": {} } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| { "took" : 1, # 查询花费的时间, 单位ms "timed_out" : false, # 是否超时 "_shards" : { # 分片信息 "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { # 搜索结果总览对象 "total" : { # 命中纪录数 "value" : 4, "relation" : "eq" }, "max_score" : 1.0, # 所有结果中最高文档得分 "hits" : [ { "_index" : "index", "_type" : "_doc", "_id" : "1", "_score" : 1.0, # 文档得分 "_source" : { # 源数据 "title" : "超大米手机" "price" : 3899.0 } }, ... ] } }
|
match查询
match
类型查询,会把查询条件进行分词,然后进行查询,默认是or关系
1 2 3 4 5 6 7 8
| GET index/_search { "query": { "match": { "title": "小米手机" } } }
|
1 2 3 4 5 6 7 8 9 10 11
| GET index/_search { "query": { "match": { "title": { "query": "小米手机", "operator": "and" } } } }
|
multi_match查询
与match查询类似,不同在于它可以在多个字段中查询
1 2 3 4 5 6 7 8 9 10
| # 在title和subTitle两个filed中查找 GET index/_search { "query": { "multi_match": { "query": "小米手机", "fields": ["title", "subTitle"] } } }
|
term词条匹配
term
查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些未分词的字符串
1 2 3 4 5 6 7 8
| GET index/_search { "query": { "term": { "price": 3899.0 } } }
|
terms多词条精确匹配
terms
查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件
1 2 3 4 5 6 7 8
| GET index/_search { "query": { "terms": { "price": [2699.0, 3899.0] } } }
|
querystring查询
1 2 3 4 5 6 7 8 9
| GET index/_search { "query": { "query_string": { "default_field": "title", "query": "小米手机" } } }
|
range范围查询
range
查询找出那些落在指定区间内的数字或者时间
- 操作符
- gt、gte、lt、lte(大于、大于等于、小于、小于等于)
1 2 3 4 5 6 7 8 9 10 11
| GET index/_search { "query": { "range": { "price": { "gte": 2000, "lte": 3000 } } } }
|
fuzzy模糊查询
fuzzy
查询是 term
查询的模糊等价。它允许搜索词条与实际词条的拼写出现偏差,但偏差的编辑距离不得超过2
1 2 3 4 5 6 7 8 9
| GET index/_search { "query": { "fuzzy": { "title": "appla" } } } # 能成功检索到apple
|
bool布尔组合查询
bool
把各种其它查询通过must
(与)、must_not
(非)、should
(或)的方式进行组合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| GET index/_search { "query": { "bool": { "must": [ { "range": { "price": { "gt": 3000 } } }, { "match": { "title": "小米" } } ] } } }
|
filter过滤
filter在bool中使用,在filter中还可以再次使用bool查询。
如果我们需要在查询结果中进行过滤,并且不希望过滤条件影响评分,那么就不要把过滤条件作为查询条件来用。而是使用filter
方式。(所有的查询都会影响到文档的评分及排名。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| GET index/_search { "query": { "bool": { "must": [ {"match": { "title": "小米手机" } } ], "filter": { "range": { "price": { "gte": 2000, "lte": 3000 } } } } } }
|
滚动查询
文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/scroll.html
使用原因:
- es 默认翻页查询最多能查前10000 条数据(可修改)
- 数据量大,性能更好
1 2 3 4 5 6 7 8 9 10 11 12 13
| GET /index/_search?scroll=1m { "query": { "match_all": {}}, "size": 100 }
GET /_search/scroll { "scroll": "1m", "scroll_id" : "" }
|
es null value
es 将不存在的值视为空值( 如:null , “” , [], {} )
1 2 3 4 5 6 7 8 9 10 11 12
| GET /index/_search { "query": { "bool": { "must_not": [ { "exists": { "field": "title"} } ] } } }
|
聚合aggregations
基本概念
bucket桶:
桶的作用,是按照某种方式对数据进行分组,每一组数据在ES中称为一个桶
,类似sql的分组。
Elasticsearch中提供的划分桶的方式有很多:
- Date Histogram Aggregation:根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组
- Histogram Aggregation:根据数值阶梯(interval)分组,与日期类似
- Terms Aggregation:根据词条内容分组,词条内容完全匹配的为一组
- Range Aggregation:数值和日期的范围分组,指定开始和结束,然后按段分组
- ……
分桶语法:
1 2 3 4 5 6 7 8 9
| GET cars/_search { "size": 0, # 不显示查询内容,只显示聚合结果 "aggs": { # 聚合 "NAME": { # 聚合名 "AGG_TYPE": {} # 分桶方式 } } }
|
metrics度量:
分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量
比较常用的一些度量聚合方式:
- Avg Aggregation:求平均值
- Max Aggregation:求最大值
- Min Aggregation:求最小值
- Percentiles Aggregation:求百分比
- Stats Aggregation:同时返回avg、max、min、sum、count等
- Sum Aggregation:求和
- Top hits Aggregation:求前几
- Value Count Aggregation:求总数
- ……
聚合为桶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| PUT /cars { "settings": { "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "transactions": { "properties": { "color": { "type": "keyword" }, "make": { "type": "keyword" } } } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| POST /cars/transactions/_bulk { "index": {}} { "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" } { "index": {}} { "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" } { "index": {}} { "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2014-05-18" } { "index": {}} { "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2014-07-02" } { "index": {}} { "price" : 12000, "color" : "green", "make" : "toyota", "sold" : "2014-08-19" } { "index": {}} { "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" } { "index": {}} { "price" : 80000, "color" : "red", "make" : "bmw", "sold" : "2014-01-01" } { "index": {}} { "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2014-02-12" }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| GET cars/_search { "size": 0, "aggs": { "popular_colors": { "terms": { "field": "color", "size": 10, # 显示的桶数 "order": { "_key": "asc" # 根据聚合的field排序 } } } } }
|
桶内度量
聚合后会默认指挥返回每个桶里面的文档数量,通常我们需要跟复杂的文档度量。
这时我们就需要度量,在aggs中添加新的aggs,即桶内的聚合,可见度量也是一个聚合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| GET cars/_search { "size": 0, "aggs": { "popular_colors": { "terms": { "field": "color", "size": 10 }, "aggs": { "avg_price": { "avg": { "field": "price" } } } } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| ... "aggregations" : { "popular_colors" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "red", "doc_count" : 4, "avg_price" : { "value" : 32500.0 } }, { "key" : "blue", "doc_count" : 2, "avg_price" : { "value" : 20000.0 } }, { "key" : "green", "doc_count" : 2, "avg_price" : { "value" : 21000.0 } } ] } }
|