文章目录
ES的安装
docker-compose安装
yaml
version: '3.8'
services:
es:
image: elasticsearch:8.14.3
container_name: es-single-8-14
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms1g -Xmx1g
ports:
- "9200:9200"
- "9300:9300"
volumes:
- ./data:/usr/share/elasticsearch/data
linux安装
- 官网下载tar包,然后传输到服务器然后解压使用
- 通过包管理器下载
bash
# Centos
yum install elasticsearch
安装ik分词器
- es以插件形式安装
bash
bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/8.4.3
- 去官网下载zip包自己解压安装
bash
elasticsearch-plugin install file:/ik/analysis-ik.zip
使用docker-compose安装es和kibana
yaml
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.14.3
container_name: elasticsearch-8.14.3
environment:
- node.name=es-node-1
- cluster.name=es-docker-cluster
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms2g -Xmx2g
- xpack.security.enabled=false
- xpack.security.enrollment.enabled=false
- xpack.ml.enabled=true
- bootstrap.memory_lock=true
- "path.repo=/usr/share/elasticsearch/backups"
ports:
- "9200:9200"
- "9300:9300"
volumes:
- ./es_data:/usr/share/elasticsearch/data
- ./backups:/usr/share/elasticsearch/backups
networks:
- elk-network
mem_limit: 4g
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q '\"status\":\"green\"' || exit 1"]
interval: 30s
timeout: 10s
retries: 3
kibana:
image: docker.elastic.co/kibana/kibana:8.14.3
container_name: kibana-8.14.3
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- SERVER_NAME=localhost
- I18N_LOCALE=zh-CN
ports:
- "5601:5601"
depends_on:
elasticsearch:
condition: service_healthy
networks:
- elk-network
mem_limit: 1g
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:5601/api/status | grep -q '\"status\":\"green\"' || exit 1"]
interval: 30s
timeout: 10s
retries: 3
# volumes:
# es_data:
# driver: local
networks:
elk-network:
driver: bridge
kibana应该有一些非常实用的场景,仅仅作为一个可视化的es dql图形化界面是很重的,跟原有的postman功能使用上会重叠
API
索引建立
自动创建索引
- 直接往一个不存在索引写入数据时自动创建
- 无法控制映射,有可能推断错误的字段类型
手动创建索引
- 自定义setting与mapping
- 可以设置为nested、数组、分词器、分词方式等高级配置
http
PUT students
{
"settings": {
"number_of_shards": 1, # 分片,不可更改
"number_of_replicas": 0, # 副本,可以随时切换
"refresh_interval": "1s", # 刷新机制,影响性能
"translog": {
"sync_interval": "5s",
"durability": "request" # 每次请求都刷盘,非常安全
},
"codec": "best_compression", # 性能与空间的比重
"analysis": { #自定义分析器,指定为ik分词器,中文分词
"analyzer": {
"ik_smart": {
"type": "custom",
"tokenizer": "ik_smart"
}
}
},
"max_result_window": 10000 #默认最大返回文档数量限制
},
# mapping 设置字段类型、是否索引、是否分词、是否聚合等
"mappings": {
"properties": {
"name": { "type": "text" },
"age": { "type": "integer" },
"class": { "type": "keyword" },
"enrolled": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis"
},
"subjects": {
"type": "nested", # 自定属性为嵌套类型
"properties": {
"subject": { "type": "keyword" },
"score": { "type": "integer" }
}
}
}
},
# 为索引绑定别名,可实现蓝绿切换、读写分离
aliases: {
}
}
模板创建
- 根据模板以及index_patterns匹配规则,可以在自动创建索引时使用模板内提前定义的setting、mapping
- 日志场景很方便
http
PUT _index_template/logs_template
{
"index_patterns": ["my-log-*"], # 索引匹配规则
"template": {
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"message": { "type": "text" },
"level": { "type": "keyword" },
"ts": { "type": "date" }
}
}
}
}
动态模板
- 可指定某索引的自动创建字段规则
- 适用于大量字段,但字段规则可预测
http
PUT students
{
"mappings": {
"dynamic_templates": [
{
"id_as_keyword": {
"match": "*_id", # 属性匹配规则
"mapping": {
"type": "keyword"
}
}
}
]
}
}
数据处理
ingest pipeline
- 可以在写入时通过指定预设的processors,在es内部完成数据处理
http
# 创建一个大写的处理
PUT _ingest/pipeline/student_pipeline
{
"processors": [
{ "uppercase": { "field": "name" } }
]
}
# 写入时指定pipeline
POST student/_doc/1?pipeline=student_pipeline
{
xxx
}
单条处理
- 单条写入的性能会很差,因为每次调用都要考虑解析文档、建立倒排索引、刷新segment
- put时,存在则覆盖,不存在则创建
- create时,已存在就报错
- update时,只更新指定的doc属性,可执行script
- update与delete可以使用byQuery方式
- script可用:
- ctx._source.xxx 访问字段
- cox.op = 'delete' 执行删除
- params.xx 外部变量
http
PUT student/_doc/1 # 可指定id
{
"name": "Tom",
"age": 18,
"math_score": 91
}
# update
POST student/_update/S001
{
"doc": {
"math": 95
}
}
# delete
DELETE student/_doc/S001
# deleteByQuery
POST student/_delete_by_query
{
"query": {
}
}
# updateByQuery,同样支持脚本
POST student/_update_by_query
{
"query": {
},
"script": {
"source": "ctx._source.math += params.score"
},
"params": {
"score": 5
}
}
批量处理
http
POST /student/_bulk
{ "index": { "_index": "student", "_id": 1 } }
{ "name": "Tom", "age": 18 }
{ "index": { "_index": "student", "_id": 2 } }
{ "name": "Jerry", "age": 19 }
- bulk是批处理,所以不仅能储存数据
- 因为是批处理,所以要求格式,第一行指定action,次行是source
- action可以使用index、update、create、delete(不用写source)
- 使用bulk时应注意大小,
- 建议处理数据前关闭数据刷新
- 导入时建议关闭副本数,避免导入期间副本同步开销
- 避免使用ingest pipeline,复杂pipeline会降低处理性能
- 对于响应结果集需要考虑处理,errors为true时代表至少有一个失败
http
#导入数据时关闭自动刷新
PUT index/_settings
{
"index": { "refresh_interval": "60s" }
}
# 导入完成后再调整回来,或者手动调用refresh
POST index/_refresh
{
}
json
{
"took": 30,
"errors": true,
"items": [
{ "index": { "_index":"student","_id":"S001","status":201 } },
{ "index": { "_index":"student","_id":"S002","status":409,"error":{ "type":"version_conflict_engine_exception", "reason":"..." } } }
]
}
日志类写入
- 监控数据与日志可以使用filebeat收集、logstash处理、es查询
平台写入
- 大数据平台写入或者各后端业务代码写入
数据查询
普通查询
- term相等
- match会分词
- wildcarde可以模糊匹配
- bool可以嵌套,可以每层单独指定minimum_should_match
http
# term查询
GET /xxx_index/_sratch?pretty
{
"query": {
"term":{
"xxx.keyword":"xxx"
}
}
}
# match查询
GET /xxx_index/_sratch?pretty
{
"query": {
"match":{
"xxx.keyword":"xxx"
}
}
}
# wildcarde查询
GET /xxx_index/_sratch?pretty
{
"query": {
"wildcard":{
"xxx.keyword":"xxx*"
}
}
}
# range查询
GET /xxx_index/_search?pretty
{
"query": {
"range":{
"startdate":{
"gte":"2025-07-24 00:00:00",
"lte": "2025-07-24 00:00:00",
"gt":"2025-07-24 00:00:00",
"lt": "2025-07-24 00:00:00"
}
}
}
}
# bool查询
GET /xxx_index/_search?pretty
{
"query": {
"bool": {
"must_not": [
{
"term": {
"xx.keyword": "D"
}
}
],
"should": [
{
"term": {
"xx": "02"
}
}
],
"must": [
{
"term": {
"xx.keyword": "WCD"
}
}
]
}
}
}
# bool多层查询,minimum_should_match可以每层bool单独设置
GET /xxx_index/_search?pretty
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"minimum_should_match": 2,
"should": [
{
"term": {
"xxx.keyword": "123"
}
},
{
"term": {
"xxx.keyword": "123"
}
}
]
}
}
]
}
}
}
查询控制
- 可通过组合from、size实现分页查询
- 可以使用
_source指定必要字段
http
# 分页查询以及排序设置,from是偏移量,sort可多个字段
GET /xxx_index/_search
{
"from":0,
"size":1,
"sort": [
{
"xxx.keyword": {
"order": "desc"
}
}
]
}
# 只展示必要字段,先走includes过滤,再走excludes过滤
GET /xxx_index/_search
{
"_source": {
"includes": ["rowkey","startdate"],
"excludes": "startdate"
}
}
结果聚合
-
关键字:
aggs,利用aggs聚合处理结果集,aggs可以嵌套 -
已预设聚合函数包括桶聚合与度量聚合
-
execution_hint可以不指定,es会自己选取。
map/global_ordinals -
示例待替换
http
GET student_scores/_search
{
"size": 0,
"aggs": {
"数学成绩统计": {
"range": {
"field": "math",
"ranges": [
{"from": 0,"to":60,"key": "D"},
{"from": 60,"to":75,"key": "C"},
{"from": 75,"to":90,"key": "B"},
{"from": 90,"to":101,"key": "A"}
]
},
"aggs": {
"班级": {
"terms": {
"field": "class"
},
"aggs": {
"range_total":{
"value_count": {
"field": "math"
}
}
}
}
}
}
}
}
- 可以使用scripted_metric自定义map-reduce脚本,分为4个脚本执行
- init_script:初始化,一般是list或map,存储中间结果
- map_script:逐条处理,每条文档都会执行
- combine_script:合并脚本,返回单个对象,一般返回init_script对象
- reduce_script:汇总脚本,拿到的是通过上述步骤的最终汇总对象
- 没遇到实际的业务场景,个人使用的场景是将某次query结果集的某个字段汇总成一个数组,后续可以直接复制到另一步骤使用
http
# 利用自定义map-reduce脚本完成对于结果的汇总,将单个字段收集为一个集合
{
"query": {
"bool":{
}
},
"aggs": {
"field_array": {
"scripted_metric": {
"init_script": "state.values = [];",
"map_script": "state.values.add(doc['xx.keyword'].value);",
"combine_script": "return state.values;",
"reduce_script": "List res = new ArrayList();for(state in states){res.addAll(state);} return res;"
}
}
}
}
预设聚合函数
桶聚合
| 聚合名 | 描述 |
|---|---|
terms |
按字段值分组,返回 top N 桶 |
histogram |
按数值字段等距分桶 |
date_histogram |
按日期字段分桶(天/周/月/年) |
range |
按数值或日期范围分桶 |
date_range |
按日期范围分桶 |
ip_range |
按 IP 范围分桶 |
filters |
按自定义查询条件分桶(多个 query) |
missing |
将缺失字段的文档分到一个桶 |
composite |
多字段组合分页分桶,支持 after_key 翻页 |
nested |
针对 nested 字段做分桶 |
reverse_nested |
从 nested 回到父文档进行聚合 |
geohash_grid |
地理坐标聚合,按格网分桶 |
geotile_grid |
高精度地理格网分桶 |
adjacency_matrix |
多 filter 组合分桶,交叉条件聚合 |
度量聚合
| 聚合名 | 描述 |
|---|---|
avg |
计算字段平均值 |
sum |
求字段和 |
min |
求字段最小值 |
max |
求字段最大值 |
stats |
综合统计:min、max、sum、count、avg |
extended_stats |
stats + 标准差、方差等 |
value_count |
文档计数,相当于 COUNT |
cardinality |
去重计数,相当于 COUNT(DISTINCT) |
percentiles |
百分位计算(50%, 90%, 95% 等) |
percentile_ranks |
某些值对应的百分位 |
top_hits |
返回每个桶的 top 文档 |
scripted_metric |
用户自定义复杂度量计算 |
median_absolute_deviation |
中位数绝对偏差(鲁棒统计) |
管道聚合
| 聚合名 | 描述 |
|---|---|
derivative |
计算数值变化率(导数) |
max_bucket |
子聚合最大值 |
min_bucket |
子聚合最小值 |
avg_bucket |
子聚合平均值 |
sum_bucket |
子聚合求和 |
stats_bucket |
子聚合统计:min/max/sum/count/avg |
extended_stats_bucket |
子聚合带标准差等统计 |
percentiles_bucket |
子聚合百分位 |
moving_avg |
移动平均 |
cumulative_sum |
累积求和 |
bucket_script |
使用脚本对子聚合进行计算 |
bucket_selector |
对桶进行筛选(相当于 HAVING) |
特殊聚合
| 聚合名 | 描述 |
|---|---|
composite |
多字段组合分页分桶 |
filters |
多 query 条件分桶 |
nested / reverse_nested |
nested 文档支持 |
adjacency_matrix |
交叉过滤条件分桶 |
geo_bounds |
返回地理边界(min/max lat/lon) |
geo_centroid |
计算地理中心点 |