文章目录
- ES基础查询
- 布尔过滤器
- 值匹配
- 范围查询
- 存在查询
- 分页
- 聚合
- 桶聚合
- 桶的嵌套
- 去重统计
- 更新数据
- ById 更新
- 查询更新
- 插入更新
- 删除数据
- ById删除
- 查询删除
- 删除索引
- 其他
- 集群健康
- 集群统计
- 索引信息
ES基础查询
*ES查询非常丰富,还有如查询性能调优、为查询配置权重、聚合中多桶排序、过滤聚合…以下仅为部分DSL入门语法 本文基于elasticsearch7.x版本
布尔过滤器
包含三种逻辑运算:与或非
{
"bool" : {
"must" : [{},{}...],
"should" : [{},{}...],
"must_not" : [{},{}...],
}
}
实例:
{
"query": {
"bool": {
"must": [
{"term": {"color": {"value": "red"}}},
{"term": {"name": {"value": "A"}}}
]
}
}
}
should条件后若要指定匹配条件:如最少满足should中一个条件,需加上minimum_should_match字段:
{
"query": {
"bool": {
"must": [{"term": {"name": {"value": "Tom"}}}],
"should": [
{"term": {"color": {"value": "red"}}},
{"term": {"name": {"value": "A"}}}
],
"minimum_should_match": 1
}
}
}
值匹配
term:字段精确匹配单个值
terms:字段匹配多个精确值
# "FIELD"字段值精确匹配"VALUE1"或"VALUE2"
{
"query": {
"terms": {
"FIELD": [
"VALUE1",
"VALUE2"
]
}
}
}
一定要了解
term
和terms
是 包含(contains) 操作,而非 等值(equals) 判断。 如何理解?如果我们有一个 term过滤器
{ "term" : { "tags" : "search" } }
,它会与以下两个文档 同时匹配:{ "tags" : ["search"] } { "tags" : ["search", "open_source"] }
match:模糊匹配:和平常理解的字符串模糊匹配有区别,match匹配依赖分词
wildcard:模糊匹配:字符串模糊匹配
{
"query": {
"wildcard": {
"postcode": "W?F*HW"
}
}
}
# ? 匹配单字符 * 匹配任意字符
match_phrase:模糊短语匹配,不用分词模式。即如“ A B”,是位置敏感匹配,会去匹配A在B前的内容
multi_match:多字段模糊匹配单个值
# 返回"model"和"name"两个字段中包含"test"的文档
{
"query": {
"multi_match": {
"query": "test",
"fields": ["name","color"]
}
}
}
match_phrase_prefix:匹配字段值以**开头
regexp:正则匹配
范围查询
range:范围查询
# 查询"age"大于等于10,小于等于20
{
"query": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
当然,也可以判断日期类型数据,加上format指定日期格式即可
{
"query": {
"range": {
"datatime": {
"gte": "2020-05-11:12:00:00",
"lte": "2021-06-11:24:00:00",
"format": "yyyy-MM-dd:HH:mm:ss"
}
}
}
}
# 当使用它处理日期字段时,range查询支持对日期计算操作,如我们想查找时间戳在过去一小时内的所有文档:
{
"range" : {
"timestamp" : {
"gt" : "now-1h"
}
}
# 更多日期格式参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping-date-format.html
范围表达式
gt
:>
大于lt
:<
小于gte
:>=
大于或等于lte
:<=
小于或等于
存在查询
对应sql中的null判断:
SELECT *
FROM table
WHERE `name` IS NULL
exists:必须存在值
必须不存在值可用must_not实现:
GET cars/_search
{
"query": {
"bool": {
"must_not": [
{"exists": {"field": "color"}}
]
}
}
}
分页
对应sql中的 limit 5,2
from – size
# 从第5条数据开始(不包括第五条),取两条:即取第6、7两条数据
{
"query": {},
"from": 5,
"size": 2
}
聚合
桶聚合
桶 简单说即满足特定条件的文档的集合(类似mysql中的分组):
- 一个人属于 男性 桶或者 女性 桶
- 张三属于 四川桶
- 日期2014-10-28属于 十月 桶
当聚合开始被执行,每个文档里面的值通过计算来决定符合哪个桶的条件。匹配到,文档将放入相应的桶并接着进行下一个聚合操作
桶也可以嵌套在其他桶里面,提供层次化或有条件的划分方案。如,张三被放入四川这个桶,而整个四川桶会被放入中国这个桶
Elasticsearch 有很多种类型的桶,能让你通过很多种方式来划分文档(时间、热词、年龄区间、地区等)。其实根本上都是通过同样的原理进行操作:基于条件来划分文档
桶聚合的两个重要概念:
- 桶(Buckets)
满足特定条件的文档的集合- 指标(Metrics)
对桶内的文档进行统计计算
类比sql中的分组:
SELECT COUNT(name)
FROM table
GROUP BY `name`
COUNT(name)
相当于指标; GROUP BY name
相当于桶
桶在概念上类似于 SQL 的分组(GROUP BY),而指标则类似于 COUNT()
、 SUM()
、 MAX()
等统计方法
简单实例:
# 在言论表中,对言论通过人员id-uid聚合(分组)
{
"size": 0,
"aggs": {
"NAME0": {
"terms": {
"field": "uid",
"size": 2
}
}
}
}
# aggs:聚合操作顶层参数 NAME0:自定义的桶名 terms:桶类型
响应:
"aggregations" : {
"NAME0" : {
"doc_count_error_upper_bound" : 2985,
"sum_other_doc_count" : 398001,
"buckets" : [
{
"key" : "211074217e7f621c4ccd46a949140332",
"doc_count" : 7333
},
{
"key" : "8780646c1e6fecd11270ef816e9bf80b",
"doc_count" : 7207
}
]
}
}
类比sql,其对应语句应为:
SELECT *
FROM `my01.dynamic`
GROUP BY `uid`
LIMIT 2
桶的嵌套
同样地,如果我们想对聚合后的桶(各个分组)进行一些分析计算,就可以使用嵌套桶,理解这个概念,可以类比sql中的having
实例:一张言论表中将言论通过uid分组后,统计各个桶中言论的点赞平均数:
{
"size": 0,
"aggs": {
"NAME0": {
"terms": {
"field": "uid",
"size": 2
},
"aggs": {
"NAME1": {
"avg": {
"field": "likeCount"
}
}
}
}
}
}
响应:
"aggregations" : {
"NAME0" : {
"doc_count_error_upper_bound" : 2985,
"sum_other_doc_count" : 398001,
"buckets" : [
{
"key" : "211074217e7f621c4ccd46a949140332",
"doc_count" : 7333,
"NAME1" : {
"value" : 694.6413473339697
}
},
{
"key" : "8780646c1e6fecd11270ef816e9bf80b",
"doc_count" : 7207,
"NAME1" : {
"value" : 613.4125156098238
}
}
]
}
}
类比sql中的having,统计聚合后组中点赞数大于20的言论:
SELECT *
FROM `my01.dynamic`
GROUP BY `uid`
HAVING `likeCount`>20
LIMIT 2
去重统计
cardinality:聚合去重统计字段
实例:言论表中将言论通过uid分组后,去重统计每个桶的言论发布类型
{
"size": 0,
"aggs": {
"NAME0": {
"terms": {
"field": "uid",
"size": 2
},
"aggs": {
"NAME1": {
"cardinality": {
"field": "postType"
}
}
}
}
}
}
响应:
"aggregations" : {
"NAME0" : {
"doc_count_error_upper_bound" : 2985,
"sum_other_doc_count" : 398733,
"buckets" : [
{
"key" : "211074217e7f621c4ccd46a949140332",
"doc_count" : 7333,
"NAME1" : {
"value" : 2
}
},
{
"key" : "8780646c1e6fecd11270ef816e9bf80b",
"doc_count" : 7207,
"NAME1" : {
"value" : 2
}
}
]
}
}
当然,也可以用于不分组的全量字段的去重统计:
{
"size": 0,
"aggs": {
"NAME": {
"cardinality": {
"field": "postType"
}
}
}
}
类比sql中的 distinct:
SELECT DISTINCT("postType")
FROM `my01.dynamic`
更新数据
ById 更新
update:通过id更新单条数据
POST my01.dynamic-000001/_update/231d2140e8649f6d30b50b3a01b07adc
{
"doc":{
"type":"评论",
"aId" : "2d277ab04ca11d52d26ed62b10df07f8"
}
}
# 格式:
POIST {index}/_update/{id}
{
"doc":{"KEY1":"VALUE1"...}
}
查询更新
_update_by_query:通过查询条件更新。用法相对复杂,单独写一篇介绍
插入更新
除了_update API可以更新文档,还可以通过插入数据的方式更新文档
实例:
# 往索引"info.feature_tag"插入id为"test172848575238167ujry8"的数据,如果该id存在,则修改该id下的数据为当前插入值
POST info.feature_tag/_doc/test172848575238167ujry8
{
"id": "test172848575238167ujr88test",
"status": "active",
"indexId": 564565,
"XxId": "test826c7aa544754aeeb2646c26814a7a78",
"Name": "名字test",
"subjectName": "项目名字test",
"province": "广东省",
"city": "深圳市",
"area": "无",
"industry": "消费",
"riskScore": 85,
"riskLevel": 2,
"values": "test"
"eventTime": "2021-06-01",
"gmtCreate": "2020-03-19 06:31:21",
"tagType": "company",
}
# 格式:
POIST {index}/_doc/{id}
{
···
}
删除数据
ById删除
用于通过文档id删除单条数据
# 删除cars索引下id=1的数据
DELETE cars/_doc/1
查询删除
删除符合查询条件的所有数据
# 删除cars索引下"color"为"white"的所有文档
POST cars/_delete_by_query
{
"query": {
"term": {
"color": {
"value": "white"
}
}
}
}
删除索引
删除整个索引,类比删除mysql中的数据库
# 删除cars索引
DELETE cars
# 响应:
{
"acknowledged" : true
}
有时因数据量较大删除到一半就返回结果了,再多执行几次就ok
其他
集群健康
GET _cluster/health
响应:
{
"cluster_name" : "elasticsearch-7-6",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 4,
"number_of_data_nodes" : 4,
"active_primary_shards" : 376,
"active_shards" : 800,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
响应中最重要的字段status,状态可能是下列三个值之一:
–
green
:所有的主分片和副本分片都已分配。集群是 100% 可用的–
yellow
:所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的–
red
:至少一个主分片(以及它的全部副本)缺失。这意味着在丢失数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回异常
number_of_nodes
和number_of_data_nodes
:节点数active_primary_shards
:集群中主分片数量,所有索引的汇总值active_shards
:所有索引的所有分片的汇总,包括副本分片relocating_shards
:显示当前正在从一个节点迁往其他节点的分片的数。通常为 0,ES 发现集群不太均衡时,该值会上涨。如:添加或下线了一个新节点initializing_shards
:刚刚创建的分片的个数。如刚创建第一个索引,分片都会短暂的处于 initializing 状态unassigned_shards
:已经在集群状态中存在的分片,但是实际在集群里又找不到。通常未分配分片的来源是未分配的副本以及它的全部副本)缺失。这意味着在丢失数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回异常
集群统计
GET _cluster/stats
# 集群的详细信息统计:集群数、状态、版本、操作系统、进程、jvm、内存、ES插件、网络等
索引信息
# 索引信息
GET my01.account/_stats
# 索引的mapping信息
GET my01.account/_mapping