简介
什么是elasticsearch?
elasticsearch是开源的分布式、Restfull 风格的数据搜索与分析引擎,是时下最流行的全文搜索引擎。
elasticsearch和Apache Lucene
Apache Lucene是时下最先进、高性能、全功能的搜索引擎库,Apache Lucene原理和实现复杂。elasticsearch就是为了解决Lucene复杂性的,elasticsearch基于Lucene,使用java语言开发,对Lucene做了一层封装,提供一套简单一致的Restfull 风格API,是的全文检索更简单。
elasticsearch不仅仅是全文搜索引擎:
安装运行
Windows下安装
step1 安装Kibana 下载Elasticsearch 6.2.2的zip包,并解压到指定目录,下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2
step2 安装中文分词插件,在elasticsearch-6.2.2\bin目录下执行以下命令
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
step3 启动es 运行es安装目录/bin/elasticsearch.bat
step4 安装Kibana 下载Kibana,作为访问Elasticsearch的客户端,请下载6.2.2版本的zip包,并解压到指定目录,下载地址:https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-windows-x86_64.zip
step5 启动Kibana 运行Kibana/bin/kibana.bat
linux下安装
step1 下载elasticsearch 6.4.0的docker镜像;
docker pull elasticsearch:6.4.0
step2 修改虚拟内存区域大小,否则会因为过小而无法启动;
sysctl -w vm.max_map_count=262144
step3 修改该目录的权限,使es有权访问目录
chmod 777 /mydata/elasticsearch/data/
step4 使用docker命令启动;
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e "cluster.name=elasticsearch" \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-d elasticsearch:6.4.0
step5 安装中文分词器IKAnalyzer,并重新启动;
docker exec -it elasticsearch /bin/bash
#此命令需要在容器中运行
#进入ES目录
docker exec -it elasticsearch /bin/bash
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.0/elasticsearch-analysis-ik-6.4.0.zip
docker restart elasticsearch
step6 访问es测试安装是否成功
http://linux服务器:9200/
step7 下载kibana 6.4.0的docker镜像
step8 docker命令启动
docker run --name kibana -p 5601:5601 \
--link elasticsearch:es \
-e "elasticsearch.hosts=http://es:9200" \
-d kibana:6.4.0
step8 访问测试安装是否成功
http://linux服务器地址:5601
Kibana是es可视化用户界面,在DevTol下可以使用es DSL语言操纵ES。
elasticsearch基本概念
全文搜索(Full-Text Search):计算机检索程序通过扫描文章每一个词,对每一个词建立索引,指明该词在文章中出现次数和位置。当用户查询时,检索程序根据事先建立的索引进行查询并返回查询结果给用户的查询方式。
倒排索引(Inverted Index):
节点 &集群(Node & Cluster):elasticsearch本质是分布式数据库,允许多台服务器共同工作。每台服务器可以运行多个es实例,单个实例就是节点(Node),一组节点构成集群(Cluster)。
索引(Index):elasticsearch管理数据的顶层单位,Index必须小写英文命名。Index相当于关系数据库中的数据库。
文档(Document):Index中的单条记录称为Document,Document使用JSON格式表示。同一个Index下Document不要求具有相同数据结构(Scheme),但是最好保持一致,这样可以提供搜索效率。
类型(Type):
文档元数据:文档元数据可以分为三部分
三者可以唯一表示一个文档。
字段:Document是一个JSON数据结构,包含许多字段,每个字段都有对应值。字段相当于关系数据库中的字段。
es和关系数据库类比图
elasticsearch入门
elasticsearch交互方式
elasticsearch提供Java API 和 Restfull API。基于Restfull API 其他语言程序可以通过9200端口和es进行通讯。
elasticsearch 请求分析
部件 | 说明 |
VERB | 适当的HTTP方法或谓词:GET\PUT\DELETE\POST\HEAD。 |
PROTOCOL | http或https(如果elasticsearch前面启用了代理) |
HOST | elasticsearch集群中任一节点主机名或者用localhost代表本地节点 |
PORT | elasticsearch端口号,默认9200 |
PATH | API终端路径(如_count将返回集群中文档数量)。PATH可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm |
QUERY_STRING | 任意可选的查询字符串参数,例如:?pretty 将格式化地输出 JSON 返回值,使其更容易阅读 |
BODY | 一个JSON格式请求体 |
HTTP方法说明
HTTP方法 | 说明 |
GET | 获取请求对象当前状态 |
PUT | 创建一个对象 |
POST | 改变当前对象状态 |
DELETE | 删除一个对象 |
HEAD | 获取对象的基础信息 |
基础命令详解
查看集群健康状态:
GET /_cat/health?v
查看节点状态:
GET /_cat/nodes?v
查看所有索引信息:
GET /_cat/indices?v
创建索引并查看;
PUT /customer
GET /_cat/indices?v
删除索引并查看:
DELETE /customer
GET /_cat/indices?v
查看文档的类型:
GET /pms/_mapping
在索引中添加文档
PUT /customer/doc/1
{
"name": "John Doe"
}
查看索引中的文档
GET /customer/doc/1
{
"_index": "customer",
"_type": "doc",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"name": "John Doe"
}
}
修改索引中的文档:
POST /customer/doc/1/_update
{
"doc": { "name": "Jane Doe" }
}
{
"_index": "customer",
"_type": "doc",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
GET /customer/doc/1
{
"_index": "customer",
"_type": "doc",
"_id": "1",
"_version": 2,
"found": true,
"_source": {
"name": "Jane Doe"
}
}
删除索引中文档:
DELETE /customer/doc/1
对索引文档进行批量操作
POST /customer/doc/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
数据搜索
elasticsearch提供了丰富灵活的查询语言-查询表达式(Query DSL),支持构建更加复杂和健壮的查询。
最简单的搜索,使用match_all
来表示,例如搜索全部:
GET /pms/_search
{
"query": { "match_all": {} }
}
分页搜索,from
表示偏移量,从0开始,size
表示每页显示的数量;
GET /pms/_search
{
"query": { "match_all": {} },
"from": 0,
"size": 3
}
搜索排序,使用sort
表示,例如按price
字段降序排列;
GET /pms/_search
{
"query": { "match_all": {} },
"sort": { "price": { "order": "desc" } }
}
搜索并返回指定字段内容,使用_source
表示,例如只返回name
和price
两个字段内容:
GET /pms/_search
{
"query": { "match_all": {} },
"_source": ["name", "price"]
}
条件搜索,使用match
表示匹配条件,例如搜索出price
为98
的文档:
GET /pms/_search
{
"query": {
"match": {
"price": 98
}
}
}
文本类型字段的条件搜索,例如搜索address
字段中包含mill
的文档,对比上一条搜索可以发现,对于数值类型match
操作使用的是精确匹配,对于文本类型使用的是模糊匹配:
GET /pms/_search
{
"query": {
"match": {
"name": "海澜之家"
}
},
"_source": [
"name",
"subTitle"
]
}
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 4.2882357,
"hits": [
{
"_index": "pms",
"_type": "product",
"_id": "30",
"_score": 4.2882357,
"_source": {
"subTitle": "2018夏季新品微弹舒适新款短T男生 6月6日-6月20日,满300减30,参与互动赢百元礼券,立即分享赢大奖",
"name": "HLA海澜之家简约动物印花短袖T恤"
}
},
{
"_index": "pms",
"_type": "product",
"_id": "32",
"_score": 4.2882357,
"_source": {
"subTitle": "HLA海澜之家短袖T恤男基础款简约圆领HNTBJ2E153A藏青(F3)175/92A(50)",
"name": "HLA海澜之家短袖T恤男基础款"
}
},
{
"_index": "pms",
"_type": "product",
"_id": "31",
"_score": 3.8090763,
"_source": {
"subTitle": "2018夏季新品短袖T恤男HNTBJ2E080A 蓝灰花纹80 175/92A/L80A 蓝灰花纹80 175/92A/L",
"name": "HLA海澜之家蓝灰花纹圆领针织布短袖T恤"
}
}
]
}
}
组合搜索
组合搜索,使用bool
来进行组合,must
表示同时满足,例如搜索subTitle
字段中同时包含2018
和男生
的文档;
GET /pms/_search
{
"query": {
"bool": {
"must": [
{ "match": { "subTitle": "2018" } },
{ "match": { "subTitle": "男生" } }
]
}
}
}
组合搜索,should
表示满足其中任意一个,搜索name
字段中包含HLA
或者海澜之家的文档
GET /pms/_search
{
"query": {
"bool": {
"should": [
{ "match": { "name": "HLA" } },
{ "match": { "name": "海澜之家" } }
]
}
}
}
组合搜索,must_not表示不同时满足,搜索subTitle字段不同时包含移动 电信的文档
GET /pms/_search
{
"query": {
"bool": {
"must_not": [
{ "match": { "subTitle": "移动" } },
{ "match": { "subTitle": "电信" } }
]
}
}
}
组合搜索,must和must_not配合,搜索name包含小米subTitle不包含电信的文档
GET /pms/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "小米" } }
],
"must_not": [
{ "match": { "subTitle": "电信" } }
]
}
}
}
过滤搜索
使用filter来表示,比如获取price在600-1000之间的商品
GET /pms/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"price": {
"gte": 600,
"lte": 1000
}
}
}
}
}
}
搜索聚合
对搜索结果进行聚合,用aggs表示,类似sql的group by 。例如对brandName进行聚合,统计出brandName相同的数目
GET /pms/_search
{
"size": 0,
"aggs": {
"group_by_brandName": {
"terms": {
"field": "brandName"
}
}
}
}
{
"took": 90,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_brandName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "小米",
"doc_count": 4
},
{
"key": "海澜之家",
"doc_count": 3
},
{
"key": "NIKE",
"doc_count": 2
},
{
"key": "华为",
"doc_count": 1
},
{
"key": "苹果",
"doc_count": 1
}
]
}
}
}
嵌套聚合,同时聚合brandName和price,计算出brandName相同的数目和price的平均值
GET /pms/_search
{
"size": 0,
"aggs": {
"group_by_brandName": {
"terms": {
"field": "brandName"
},
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
{
"took": 123,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_brandName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "小米",
"doc_count": 4,
"average_price": {
"value": 2461.5
}
},
{
"key": "海澜之家",
"doc_count": 3,
"average_price": {
"value": 88
}
},
{
"key": "NIKE",
"doc_count": 2,
"average_price": {
"value": 434
}
},
{
"key": "华为",
"doc_count": 1,
"average_price": {
"value": 3788
}
},
{
"key": "苹果",
"doc_count": 1,
"average_price": {
"value": 5499
}
}
]
}
}
}
对聚合搜索的结果进行排序
GET /pms/_search
{
"size": 0,
"aggs": {
"group_by_brandName": {
"terms": {
"field": "brandName",
"order": {
"average_price": "desc"
}
},
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
{
"took": 39,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_brandName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "苹果",
"doc_count": 1,
"average_price": {
"value": 5499
}
},
{
"key": "华为",
"doc_count": 1,
"average_price": {
"value": 3788
}
},
{
"key": "小米",
"doc_count": 4,
"average_price": {
"value": 2461.5
}
},
{
"key": "NIKE",
"doc_count": 2,
"average_price": {
"value": 434
}
},
{
"key": "海澜之家",
"doc_count": 3,
"average_price": {
"value": 88
}
}
]
}
}
}
参考 https://mp.weixin.qq.com/s/cohWZy_eUOUqbmUxhXzzNA