elasticsearch 查询语法

查询文档

一、精确匹配单个字段

elasticsearch的term查询,下面给出完整的代码
1
2
3
4
5
6
7
8
9
10
11
// 创建term查询条件,用于精确查询
termQuery := elastic.NewTermQuery("Author", "tizi")

searchResult, err := client.Search().
Index("blogs"). // 设置索引名
Query(termQuery). // 设置查询条件
Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
From(0). // 设置分页参数 - 起始偏移量,从第0行记录开始
Size(10). // 设置分页参数 - 每页大小
Pretty(true). // 查询结果返回可读性较好的JSON格式
Do(ctx) // 执行请求

模糊匹配 match、fuzzy、wildCard

match
分词匹配检索, 按照默认分词器将传入参数进行分词,如下面例子会分成老、板进行检索
1
elastic.NewMatchQuery("name", "老板")
得到的结果可能是:
1
2
3
4
5
老板
老板娘
老公
老人
模板
wildcard
通配符检索,即相当于sql的like,在前后拼接*,匹配0到多个任意字符;也可使用?匹配单个字符
1
elastic.NewWildcardQuery("name", "*li*")
得到的结果可能是:
1
2
3
4
lisi
lily
lisa
limon
注意:在业务场景中应该警惕使用wildcard检索。以*或?开头的检索,会增加查询匹配需要的迭代次数并降低搜索性能,增大带有通配符构造出来的DFA(Deterministic Finite Automaton)的复杂堵,导致CPU开销增大,从而导致集群宕机的风险。那有什么解决类似mysql like查询的方案吗?
fuzzy
模糊/纠错检索, 对输入参数进行一定程度的容错
1
elastic.NewFuzzyQuery("name", "李四")
得到的结果可能是:
1
2
3
李四
李连杰
李晨

二、通过terms实现SQL的in查询

通过terms查询语法实现,多值查询效果
1
2
3
4
5
6
7
8
9
10
// 创建terms查询条件
termsQuery := elastic.NewTermsQuery("Author", "tizi", "tizi365")

searchResult, err := client.Search().
Index("blogs"). // 设置索引名
Query(termsQuery). // 设置查询条件
Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
From(0). // 设置分页参数 - 起始偏移量,从第0行记录开始
Size(10). // 设置分页参数 - 每页大小
Do(ctx) // 执行请求

三、匹配单个字段

某个字段使用全文搜索,也就是ES的match语法
例子:
1
2
3
4
5
6
7
8
9
10
// 创建match查询条件
matchQuery := elastic.NewMatchQuery("Title", "golang es教程")

searchResult, err := client.Search().
Index("blogs"). // 设置索引名
Query(matchQuery). // 设置查询条件
Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
From(0). // 设置分页参数 - 起始偏移量,从第0行记录开始
Size(10). // 设置分页参数 - 每页大小
Do(ctx)

四、范围查询

实现类似Created > ‘2020-07-20’ and Created < ‘2020-07-22’的范围查询条件
range 表示获取指定字段值的范围,相当于sql中的 <> ,其中gt为 > , lt为 < ,gte为 >=, lte为 <=;
创建查询表达式例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 例1 等价表达式: Created > "2020-07-20" and Created < "2020-07-29"
rangeQuery := elastic.NewRangeQuery("Created").
Gt("2020-07-20").
Lt("2020-07-29")

// 例2 等价表达式: id >= 1 and id < 10
rangeQuery := elastic.NewRangeQuery("id").
Gte(1).
Lte(10)

elastic.NewRangeQuery("msgTime").
Gte("2023-01-01 00:00:00").Lt("2023-12-30 23:59:59").
Format("yyyy-MM-dd HH:mm:ss").TimeZone("+08:00")

五、bool组合查询

bool组合查询,实际上就是组合了前面的查询条件,然后通过类似SQL语句的and和or将查询条件组合起来,不熟悉ES查询语法,请参考ES教程

5.1. must条件

类似SQL的and,代表必须匹配的条件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 创建bool查询
boolQuery := elastic.NewBoolQuery().Must()

// 创建term查询
termQuery := elastic.NewTermQuery("Author", "tizi")
matchQuery := elastic.NewMatchQuery("Title", "golang es教程")

// 设置bool查询的must条件, 组合了两个子查询
// 表示搜索匹配Author=tizi且Title匹配"golang es教程"的文档
boolQuery.Must(termQuery, matchQuery)

searchResult, err := client.Search().
Index("blogs"). // 设置索引名
Query(boolQuery). // 设置查询条件
Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
From(0). // 设置分页参数 - 起始偏移量,从第0行记录开始
Size(10). // 设置分页参数 - 每页大小
Do(ctx) // 执行请求

5.2. must_not条件

跟must的作用相反,用法和must类似
1
2
3
4
5
6
7
8
// 创建bool查询
boolQuery := elastic.NewBoolQuery().Must()

// 创建term查询
termQuery := elastic.NewTermQuery("Author", "tizi")

// 设置bool查询的must not条件
boolQuery.MustNot(termQuery)

5.3. should条件

类似SQL中的 or, 只要匹配其中一个条件即可
1
2
3
4
5
6
7
8
9
10
// 创建bool查询
boolQuery := elastic.NewBoolQuery().Must()

// 创建term查询
termQuery := elastic.NewTermQuery("Author", "tizi")
matchQuery := elastic.NewMatchQuery("Title", "golang es教程")

// 设置bool查询的should条件, 组合了两个子查询
// 表示搜索Author=tizi或者Title匹配"golang es教程"的文档
boolQuery.Should(termQuery, matchQuery)

5.2. filter条件

filter 表示根据过滤条件得到满足的文档;
1
q.Filter(elastic.NewTermQuery("account", "1"))

5.2. terms条件

terms 表示为匹配指定字段的多个值 ,相当于sql中的 in ;
1
elastic.NewTermsQueryFromStrings("name", []string{"zhangsan", "lisi"})

5.2. exists条件

exists 表示判断是否存在, 既可以判断该字段是否在es中是否为空
1
elastic.NewExistsQuery("name")

六、 Aggregation(聚合)

6.1. es聚合类型:

1. Bucketing aggregation, 类似mysql 的group by;
2. Metric aggregation, 数学运算,对文档统计分析
3. Matrix aggregation,对多个字段进行操作返回一个矩阵结果;
4. Pipeline aggregation,聚合结果进行二次聚合

6.2. 指标聚合

Value Count
值聚合,统计文档总数,等同于sql的count函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
client, err := elastic.NewClient()
if err != nil {
// Handle error
panic(err)
}

aggs := elastic.NewValueCountAggregation().Field("type")

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("total", aggs).
Size(0).
Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
agg, found := searchResult.Aggregations.ValueCount("total")
if !found {
//todo
}

6.2. Cardinality

基数聚合,等同sql的count(DISTINCT 字段)
1
2
3
4
5
6
7
8
9
10
11
12
aggs := elastic.NewCardinalityAggregation().
Field("type")

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("total", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Cardinality("total")
...

6.3. Avg

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewAvgAggregation().Field("price") 

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("avg_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Avg("avg_price")
...

6.4. Sum

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewSumAggregation().Field("price")

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("total_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Sum("total_price")
...

6.5. Max

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewAvgAggregation().Field("price") 

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("avg_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Avg("avg_price")
...

6.3. Avg

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewAvgAggregation().Field("price") 

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("avg_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Avg("avg_price")
...

6.3. Avg

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewAvgAggregation().Field("price") 

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("avg_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Avg("avg_price")
...

6.4. Max

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewMaxAggregation().Field("price")

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("max_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Max("max_price")
...

6.5. Min

1
2
3
4
5
6
7
8
9
10
11
aggs := elastic.NewMinAggregation().Field("price")

searchResult, err := client.Search().
Index("good").
Query(elastic.NewMatchAllQuery()).
Aggregation("min_price", aggs).
Size(0).
Do(context.Background())
...
agg, found := searchResult.Aggregations.Min("min_price")
...

6.4. Terms Aggregation : group by

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
client, err := elastic.NewClient()
if err != nil {
// Handle error
panic(err)
}
agetop := elastic.NewtermsAggregation().Field("age")
result, err := client.Search().Index("twitter").
Query(elastic.NewMatchAllQuery()).
Aggregation("agetop", agetop).
Size(0).
Do(context.Backgroud())
agg, found := result.Aggregations.Terms("agetop")
if !found {
// todo
}
for _, ageBucket := range agg.Buckets {
age := ageBucket.Key
}
...

6.4. Histogram聚合

直方图聚合即根据数值间隔分组,histogram聚合分桶统计结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
client, err := elastic.NewClient()
if err != nil {
// Handle error
panic(err)
}
aggs := elastic.NewHistogramAggregation().
Field("age").Interval(10) // 年龄间隔10分组

result, err := client.Search().
Index("twitter").
Query(elastic.NewMatchAllQuery()).
Aggregation("age", aggs).
Size(0)
Do(context.Background())
if err!= nil {
// todo
}
agg, found := result.Aggregations.Histogram("age")
if !found {
// todo
}
for _,bucket := range agg.Buckets {
value := bucket.Key
}

6.4. Date histogram聚合

功能类似于histogram聚合,主要作用为处理时间类型之短,根据时间、日期进行分桶统计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
aggs := elastic.NewDateHistogramAggregation().
Field("createTime").
// 分组间隔:month代表每月、支持minute(每分钟)、hour(每小时)、day(每天)、week(每周)、year(每年)
CalendarInterval("month").
// 设置返回结果中桶key的时间格式
Format("yyyy-MM-dd")

searchResult, err := client.Search().
Index("twitter").
Query(elastic.NewMatchAllQuery()).
Aggregation("create_time", aggs).
Size(0).
Do(ctx)
if err!= nil {
// todo
}
agg, found := result.Aggregations.Histogram("create_time")
if !found {
// todo
}

6.4. Range聚合

按照数值范围进行分桶统计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
aggs := elastic.NewRangeAggregation().
Field("price").
Keyed(true).
LtWithKey("cheap", 70).
BetweenWithKey("average", 70, 200).
GtWithKey("expensive", 200)

searchResult, err := client.Search().
Index("twitter").
Query(elastic.NewMatchAllQuery()).
Aggregation("prices", aggs).
Size(0).
Do(ctx)
if err!= nil {
// todo
}
agg, found := result.Aggregations.Range("prices")

https://www.tizi365.com/archives/858.html

https://www.modb.pro/db/147001

https://juejin.cn/post/7245919919224815671