好玩的ES--第四篇之聚合查询和集群
- 聚合查询
- 简介
- 测试数据
- 使用
- 根据某个字段分组
- 求最大值
- 求最小值
- 求平均值
- 求和
- 整合应用
- 集群
- 集群 Cluster
- 相关概念
- 集群<cluster>
- 节点<node>
- 索引<Index>
- 映射<Mapping>
- 文档<Document>
- 分片<shards>
- 复制<replicas>
- 搭建集群
- 集群规划
- 配置文件
- 编写 compose 文件
- kibana 配置文件
- 查看集群状态
- 安装head插件
- 相关概念
- 集群 Cluster
聚合查询
简介
聚合:英文为Aggregation,是es除搜索功能外提供的针对es数据做统计分析的功能。聚合有助于根据搜索查询提供聚合数据。聚合查询是数据库中重要的功能特性,ES作为搜索引擎兼数据库,同样提供了强大的聚合分析能力。它基于查询条件来对数据进行分桶、计算的方法。有点类似于 SQL 中的 group by 再加一些函数方法的操作。
注意事项:text类型是不支持聚合的。
测试数据
代码语言:javascript复制# 创建索引 index 和映射 mapping
PUT /fruit
{
"mappings": {
"properties": {
"title":{
"type": "keyword"
},
"price":{
"type":"double"
},
"description":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
-
# 放入测试数据
PUT /fruit/_bulk
{"index":{}}
{"title" : "面包","price" : 19.9,"description" : "小面包非常好吃"}
{"index":{}}
{"title" : "旺仔牛奶","price" : 29.9,"description" : "非常好喝"}
{"index":{}}
{"title" : "日本豆","price" : 19.9,"description" : "日本豆非常好吃"}
{"index":{}}
{"title" : "小馒头","price" : 19.9,"description" : "小馒头非常好吃"}
{"index":{}}
{"title" : "大辣片","price" : 39.9,"description" : "大辣片非常好吃"}
{"index":{}}
{"title" : "透心凉","price" : 9.9,"description" : "透心凉非常好喝"}
{"index":{}}
{"title" : "小浣熊","price" : 19.9,"description" : "童年的味道"}
{"index":{}}
{"title" : "海苔","price" : 19.9,"description" : "海的味道"}
使用
根据某个字段分组
代码语言:javascript复制# 根据某个字段进行分组 统计数量
GET /fruit/_search
{
"query": {
"term": {
"description": {
"value": "好吃"
}
}
},
"aggs": {
"price_group": {
"terms": {
"field": "price"
}
}
}
}
求最大值
代码语言:javascript复制# 求最大值
GET /fruit/_search
{
"aggs": {
"price_max": {
"max": {
"field": "price"
}
}
}
}
求最小值
代码语言:javascript复制# 求最小值
GET /fruit/_search
{
"aggs": {
"price_min": {
"min": {
"field": "price"
}
}
}
}
求平均值
代码语言:javascript复制# 求平均值
GET /fruit/_search
{
"aggs": {
"price_agv": {
"avg": {
"field": "price"
}
}
}
}
求和
代码语言:javascript复制# 求和
GET /fruit/_search
{
"aggs": {
"price_sum": {
"sum": {
"field": "price"
}
}
}
}
整合应用
代码语言:javascript复制// 求不同价格的数量
@Test
public void testAggsPrice() throws IOException {
SearchRequest searchRequest = new SearchRequest("fruit");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.terms("group_price").field("price"));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
ParsedDoubleTerms terms = aggregations.get("group_price");
List<? extends Terms.Bucket> buckets = terms.getBuckets();
for (Terms.Bucket bucket : buckets) {
System.out.println(bucket.getKey() ", " bucket.getDocCount());
}
}
代码语言:javascript复制// 求不同名称的数量
@Test
public void testAggsTitle() throws IOException {
SearchRequest searchRequest = new SearchRequest("fruit");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.terms("group_title").field("title"));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
ParsedStringTerms terms = aggregations.get("group_title");
List<? extends Terms.Bucket> buckets = terms.getBuckets();
for (Terms.Bucket bucket : buckets) {
System.out.println(bucket.getKey() ", " bucket.getDocCount());
}
}
代码语言:javascript复制// 求和
@Test
public void testAggsSum() throws IOException {
SearchRequest searchRequest = new SearchRequest("fruit");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.sum("sum_price").field("price"));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
ParsedSum parsedSum = searchResponse.getAggregations().get("sum_price");
System.out.println(parsedSum.getValue());
}
集群
ES集群类似Redis的分片集群加主从集群架构
集群 Cluster
相关概念
集群
一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能
。一个集群由一个唯一的名字标识,这个名字默认就是elasticsearch
。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。
节点
一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。
索引
一组相似文档的集合
映射
用来定义索引存储文档的结构如:字段、类型等。
文档
索引中一条记录,可以被索引的最小单元
分片
Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置 到集群中的任何节点上。
复制
Index的分片中一份或多份副本。
搭建集群
集群规划
代码语言:javascript复制# 1.准备3个ES节点和一个kibana 节点 ES 9200 9300
- web: 9201 tcp:9301 node-1 elasticsearch.yml
- web: 9202 tcp:9302 node-2 elasticsearch.yml
- web: 9203 tcp:9303 node-3 elasticsearch.yml
- kibana: 5602
- 注意
- 所有节点集群名称必须一致 cluster.name
- 每个节点必须有一个唯一名字 node.name
- 开启每个节点远程连接 network.host: 0.0.0.0
- 指定使用 IP地址进行集群节点通信 network.publish_host:
- 修改 web 端口 tcp 端口 http.port: transport.tcp.port
- 指定集群中所有节点通信列表 discovery.seed_hosts: node-1 node-2 node-3 相同
- 允许集群初始化 master 节点节点数: cluster.initial_master_nodes: [“node-1”, “node-2”,“node-3”]
- 集群最少几个节点可用 gateway.recover_after_nodes: 2
- 开启每个节点跨域访问http.cors.enabled: true http.cors.allow-origin: “*”
配置文件
代码语言:javascript复制# node-1 配置文件
代码语言:javascript复制# 指定集群名称 3个节点必须一致
cluster.name: es-cluster
# 指定节点名称 每个节点名字唯一
node.name: node-1
# 开放远程链接
network.host: 0.0.0.0
# 指定使用发布地址进行集群间通信
network.publish_host: 192.168.124.3
# 指定 web 端口
http.port: 9201
# 指定 tcp 端口
transport.tcp.port: 9301
# 指定所有节点的 tcp 通信
discovery.seed_hosts: ["192.168.124.3:9301", "192.168.124.3:9302","192.168.124.3:9303"]
# 指定可以初始化集群的节点名称
cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
# 集群最少几个几点可用
gateway.recover_after_nodes: 2
# 解决跨域问题
http.cors.enabled: true
http.cors.allow-origin: "*"
代码语言:javascript复制# node-2 配置文件
代码语言:javascript复制# 指定集群名称 3个节点必须一致
cluster.name: es-cluster
# 指定节点名称 每个节点名字唯一
node.name: node-2
# 开放远程链接
network.host: 0.0.0.0
# 指定使用发布地址进行集群间通信
network.publish_host: 192.168.124.3
# 指定 web 端口
http.port: 9202
# 指定 tcp 端口
transport.tcp.port: 9302
# 指定所有节点的 tcp 通信
discovery.seed_hosts: ["192.168.124.3:9301", "192.168.124.3:9302","192.168.124.3:9303"]
# 指定可以初始化集群的节点名称
cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
# 集群最少几个几点可用
gateway.recover_after_nodes: 2
# 解决跨域问题
http.cors.enabled: true
http.cors.allow-origin: "*"
代码语言:javascript复制# node-3 配置文件
代码语言:javascript复制# 指定集群名称 3个节点必须一致
cluster.name: es-cluster
# 指定节点名称 每个节点名字唯一
node.name: node-2
# 开放远程链接
network.host: 0.0.0.0
# 指定使用发布地址进行集群间通信
network.publish_host: 192.168.124.3
# 指定 web 端口
http.port: 9202
# 指定 tcp 端口
transport.tcp.port: 9302
# 指定所有节点的 tcp 通信
discovery.seed_hosts: ["192.168.124.3:9301", "192.168.124.3:9302","192.168.124.3:9303"]
# 指定可以初始化集群的节点名称
cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
# 集群最少几个几点可用
gateway.recover_after_nodes: 2
# 解决跨域问题
http.cors.enabled: true
http.cors.allow-origin: "*"
编写 compose 文件
代码语言:javascript复制version: "3.8"
networks:
escluster:
services:
es01:
image: elasticsearch:7.14.0
ports:
- "9201:9201"
- "9301:9301"
networks:
- "escluster"
volumes:
- ./node-1/data:/usr/share/elasticsearch/data
- ./node-1/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./node-1/plugins/ik:/usr/share/elasticsearch/plugins/ik
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
es02:
image: elasticsearch:7.14.0
ports:
- "9202:9202"
- "9302:9302"
networks:
- "escluster"
volumes:
- ./node-2/data:/usr/share/elasticsearch/data
- ./node-2/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./node-2/plugins/ik:/usr/share/elasticsearch/plugins/ik
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
es03:
image: elasticsearch:7.14.0
ports:
- "9203:9203"
- "9303:9303"
networks:
- "escluster"
volumes:
- ./node-3/data:/usr/share/elasticsearch/data
- ./node-3/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./node-3/plugins/ik:/usr/share/elasticsearch/plugins/ik
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
kibana:
image: kibana:7.14.0
ports:
- "5602:5601"
networks:
- "escluster"
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
kibana 配置文件
代码语言:javascript复制# kibana配置文件 连接到ES
server.host: "0"
server.shutdownTimeout: "5s"
elasticsearch.hosts: [ "http://192.168.124.3:9201" ] #链接任意节点即可
monitoring.ui.container.elasticsearch.enabled: true
查看集群状态
代码语言:javascript复制http://10.102.115.3:9200/_cat/health?v
安装head插件
代码语言:javascript复制1. 访问github网站
搜索: elasticsearch-head 插件
2. 安装git
yum install git
3. 将elasticsearch-head下载到本地
git clone git://github.com/mobz/elasticsearch-head.git
4. 安装nodejs
#注意: 没有wget的请先安装yum install -y wget
wget http://cdn.npm.taobao.org/dist/node/latest-v8.x/node-v8.1.2-linux-x64.tar.xz
5. 解压缩nodejs
xz -d node-v10.15.3-linux-arm64.tar.xz
tar -xvf node-v10.15.3-linux-arm64.tar
6. 配置环境变量
mv node-v10.15.3-linux-arm64 nodejs
mv nodejs /usr/nodejs
vim /etc/profile
export NODE_HOME=/usr/nodejs
export PATH=$wPATH:$JAVA_HOME/bin:$NODE_HOME/bin
7. 进入elasticsearch-head的目录
npm config set registry https://registry.npm.taobao.org
npm install
npm run start
8. 启动访问head插件 默认端口9100
http://ip:9100 查看集群状态