Elasticsearch 核心查询解决 90% 查询场景

编程入门 行业动态 更新时间:2024-10-11 01:12:29

Elasticsearch 核心查询解决 90% 查询<a href=https://www.elefans.com/category/jswz/34/1770727.html style=场景"/>

Elasticsearch 核心查询解决 90% 查询场景

写在前面

官方文档地址

ES 的查询语言称为 DSL 即 Domain Specific Language 领域专用语言。

本文查询将以下列索引结构为例子展开。

PUT /dying_gq_bookstore
{"mappings": {"properties": {"book_id": {"type": "long"},"title": {"type": "text"},"tag": {"type": "keyword"},"book_type": {"type": "keyword"},"content": {"type": "text"},"status": {"type": "keyword"},"price": {"type": "long"},"stock":{"type": "long"}}}
}
POST /dying_gq_bookstore
{"index": {}}
{"book_id": 1,"title": "离开时请叫醒我","tag": "情感","book_type": "畅销文学","content": "不论如何,离开时请告诉我","status": 1,"price": "48","stock": 20000}
{"index": {}}
{"book_id": 1,"title": "我想要两个西柚","tag": "情感","book_type": "畅销文学","content": "i want to see you","status": 1,"price": "39","stock": 6000}
{"index": {}}
{"book_id": 1,"title": "清风徐来","tag": "情感","book_type": "畅销文学","content": "随波逐流","status": 1,"price": "36","stock": 18622}
{"index": {}}
{"book_id": 1,"title": "迷途","tag": "悬疑","book_type": "畅销文学","content": "生活如待宰羔羊","status": 2,"price": "54","stock": 543}
{"index": {}}
{"book_id": 1,"title": "八百万种死法","tag": "悬疑","book_type": "外国文学","content": "这个城市八百万种人,八百万种死法","status": 2,"price": "69","stock": 888}
{"index": {}}
{"book_id": 1,"title": "福尔摩斯与他的狗","tag": "悬疑","book_type": "外国文学","content": "这只狗已经老去好久了","status": 2,"price": "198","stock": 88932}
{"index": {}}
{"book_id": 1,"title": "只能陪你走一程","tag": "治愈","book_type": "治愈文学","content": "抱歉我只能陪你走到这了","status": 2,"price": "38","stock": 765}
{"index": {}}
{"book_id": 1,"title": "一点点","tag": "交通","book_type": "交通治安","content": "能拉但只能拉一点点","status": 1,"price": "99","stock": 18833}
{"index": {}}
{"book_id": 1,"title": "成华大道","tag": "交通","book_type": "交通治安","content": "我该不该走成华大道","status": 1,"price": "23","stock": 2334}
{"index": {}}
{"book_id": 1,"title": "华仙桥","tag": "交通","book_type": "交通治安","content": "华仙桥旅行指南","status": 1,"price": "19","stock": 210}

核心类型

  • 字符串:string,string类型包含 text 和 keyword。
    • text:该类型被用来索引长文本,在创建索引前会将这些文本进行分词,转化为词的组合,建立索引;允许es来检索这些词,text类型不能用来排序和聚合。
    • keyword:该类型不能分词,可以被用来检索过滤、排序和聚合,keyword类型不可用text进行分词模糊检索。
  • 数值型:long、integer、short、byte、double、float
  • 日期型:date

1.单条件查询

注以下部分查询会给出 类似 SQL 辅助理解,因倒排索引 term 匹配关系 SQL 是近似并非一定等效,一定注意

模糊匹配

以下模糊匹配都是基于 分词器 对 原本内容分词后 的 term 做匹配得出的效果。
(声明一下,一下所有查询都可以通过合适的语法组合起来进行更加复杂的查询)

match 分词模糊匹配

对搜索词分词后,查询匹配搜索列分词后的 term
如下例子 “你好呀世界” 可能会被分词为 “你好”、“世界”、“你”、“好”。(根据分词器的不同分词不同)
然后匹配倒排索引的 content 的 term。

POST /dying_gq_bookstore/_search
{"from": 0, //分页 从 0 个开始"size": 20, // 后 20 条数据 意义同 mysql limit 0,20"query": {"match": {// 对搜索词分词后 匹配字段内容分词后的 term"content": "你好呀世界" // 字段 :匹配内容}}
}

类似 SQL:SELECT * FROM dying_gq_bookstore WHERE content LIKE '%你好呀世界%' LIMIT 0,20

prefix 前缀模糊匹配

POST /dying_gq_bookstore/_search
{"from": 0, //分页 从 0 个开始"size": 20, // 后 20 条数据 意义同 mysql limit 0,20"query": {"prefix": {// 匹配字段内容分词后 term 的前缀"content": "你好呀世界" // 字段 :匹配内容}}
}

类似 SQL:SELECT * FROM dying_gq_bookstore WHERE content LIKE '你好呀世界%' LIMIT 0,20

regexp 正则匹配

POST /dying_gq_bookstore/_search
{"from": 0, //分页 从 0 个开始"size": 20, // 后 20 条数据 意义同 mysql limit 0,20"query": {"regexp": {// 分词 正则匹配字段内容分词 term "content": "[1-9]" // 字段 :匹配内容}}
}
精确匹配

term 单个字段单条件精确匹配

精确匹配分词后的 term,和 match 的区别在于不会对你要匹配的词进行分词。

POST /dying_gq_bookstore/_search
{"from": 0, //分页 从 0 个开始"size": 20, // 后 20 条数据 意义同 mysql limit 0,20"query": {"match": {// 匹配字段内容分词后的 term"content": "你好呀世界" // 字段 :匹配内容}}
}

类似 SQL:SELECT * FROM dying_gq_bookstore WHERE content = '你好呀世界' LIMIT 0,20

terms 单个字段多条件精确匹配

数组内的值相当于 or 的关系

POST /dying_gq_bookstore/_search
{"from": 0, //分页 从 0 个开始"size": 20, // 后 20 条数据 意义同 mysql limit 0,20"query": {"terms": {"content": ["你好","时间","不错"]}}
}

类似 SQL:SELECT * FROM dying_gq_bookstore WHERE content = '你好' OR content = '时间' OR content = '不错' LIMIT 0,20

range 范围内精确匹配

POST /dying_gq_bookstore/_search
{"from": 0, //分页 从 0 个开始"size": 20, // 后 20 条数据 意义同 mysql limit 0,20"query": {"range": {"book_id": {"gte": 10, //大于"lte": 20 //小于}}}
}

类似 SQL:SELECT * FROM dying_gq_bookstore WHERE between 10 and 20 LIMIT 0,20

2.组合条件查询

bool 查询

可组合条件:

must : 各个条件都必须满足,即各条件是and的关系
should : 各个条件有一个满足即可,即各条件是or的关系
must_not : 不满足所有条件,即各条件是not的关系
filter : 不计算相关度评分,它不计算_score即相关度评分,效率更高

POST /dying_gq_bookstore/_search
{"query": { "bool": { "must": [{ "match": { "title":   "Search"        }},{ "match": { "content": "Elasticsearch" }}],"filter": [ { "term":  { "status": "published" }},{ "range": { "book_id": { "gte": "200" }}}]}}
}

3.聚合搜索

bucket: bucket 为分组后个每个桶
metric: metric 为每个桶中的统计分析(如 数量、最大值、最小值等)

注意 text 类型无法聚合

样例 1 :普通聚合

样例 1 查询语义为:

对 dying_gq_bookstore 索引按字段 tag 分组聚合 ,统计不同 tag 的数量并 按数量 升序排序。

POST /dying_gq_bookstore/_search
{"size": 0, // 此处设置 size = 0 表示不返回 ES 数据文档,仅返回聚合后数据"aggs": { // 聚合"group_by_tag": { // 聚合名称,可以自定义名称"terms": {//聚合匹配方式"field": "tag", // 列名"order": { // 排序"_count": "asc" // 根据个数 升序 _count 为固定写法}}}}
}

样例 2 : 嵌套聚合 下钻分析

样例 2 查询语义为:

对 dying_gq_bookstore 索引按字段 tag 分组聚合 。并在此基础上对每个桶做统计分析即 metric ,求每个 bucket tag 分组下的书籍平均价格 并 按平均价格 升序排序。这种嵌套聚合的方式又称为 下钻分析

POST /dying_gq_bookstore/_search
{"size": 0, "aggs": { // 聚合"group_by_tag": { // 聚合名称,可以自定义名称"terms": {//聚合匹配方式"field": "tag", // 列名"order": { // 排序"avg_by_price": "asc" // 求取的平均价格 升序 这里命名的作用就显示出来了}},"aggs": { // 再次聚合 嵌套聚合 下钻分析"avg_by_price": { // 聚合名称"avg": { // 求平均值"field": "price" // 平均值列名称}}}}}
}

样例 3 : 多重嵌套聚合

样例 3 查询语义为:

以 tag 标签分组后 分析该标签下书籍平均价格,并以 tag 分组的 bucket 为基础 以 book_type 再进行子分组,子分组以 book_type 平均价格升序排序,外部 tag 分组以 tag 平均价格升序排序。

POST /dying_gq_bookstore/_search
{"size": 0, "aggs": { "group_by_tag": { "terms": {"field": "tag", "order": { "avg_by_price_tag": "asc"  }},"aggs": { "avg_by_price_tag": { "avg": { "field": "price" }},"group_by_book_type":{"terms": {"field": "book_type","order": {"avg_by_price_book_type": "asc"}},"aggs": {"avg_by_price_book_type": {"avg": {"field": "price"}}}}}}}
}

为帮助理解,这里贴出查询结果如下:

{"took" : 1,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 10,"relation" : "eq"},"max_score" : null,"hits" : [ ]},"aggregations" : {"group_by_tag" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "治愈","doc_count" : 1,"avg_by_price_tag" : {"value" : 38.0},"group_by_book_type" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "治愈文学","doc_count" : 1,"avg_by_price_book_type" : {"value" : 38.0}}]}},{"key" : "情感","doc_count" : 3,"avg_by_price_tag" : {"value" : 41.0},"group_by_book_type" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "畅销文学","doc_count" : 3,"avg_by_price_book_type" : {"value" : 41.0}}]}},{"key" : "交通","doc_count" : 3,"avg_by_price_tag" : {"value" : 47.0},"group_by_book_type" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "交通治安","doc_count" : 3,"avg_by_price_book_type" : {"value" : 47.0}}]}},{"key" : "悬疑","doc_count" : 3,"avg_by_price_tag" : {"value" : 107.0},"group_by_book_type" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "畅销文学","doc_count" : 1,"avg_by_price_book_type" : {"value" : 54.0}},{"key" : "外国文学","doc_count" : 2,"avg_by_price_book_type" : {"value" : 133.5}}]}}]}}
}

样例 4 : 聚合多分析

样例 4 查询语义为:

以 book_type 分组,统计分析组内 价格最大值、最小值、和总值

POST /dying_gq_bookstore/_search
{"size": 0,"aggs": {"group_by_book_type": {"terms": {"field": "book_type","order": {"price_min": "asc"}},"aggs": {"price_max": {"max": {"field": "price"}},"price_min":{"min": {"field": "price"}},"price_sum":{"sum": {"field": "price"}}}}}
}

样例 5 : 聚合分组最大值

样例 5 查询语义为:

以 book_type 分组,统计分析组内价格最大的书籍并展示

POST /dying_gq_bookstore/_search
{"size": 0,"aggs": {"group_by_book_type": {"terms": {"field": "book_type"},"aggs": {"top_price": {"top_hits": {"size": 1,"sort": [{"price": {"order": "desc"}}]}}}}}
}

样例 6 : 区间分组统计

样例 6 查询语义为:

以 price 书籍价格分组 分组间隔为 20 :[0,20) [20,40) [40,60) ……。并统计分组内最大书籍价格

POST /dying_gq_bookstore/_search
{"size": 0,"aggs": {"histogram_by_price": {"histogram": {"field": "price","interval": 20 // 分组间隔 },"aggs": {"max_by_price": {"max": {"field": "price"}}}}}
}

为帮助理解,这里贴出查询结果如下:

{"took" : 1,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 10,"relation" : "eq"},"max_score" : null,"hits" : [ ]},"aggregations" : {"histogram_by_price" : {"buckets" : [{"key" : 0.0,"doc_count" : 1,"max_by_price" : {"value" : 19.0}},{"key" : 20.0,"doc_count" : 4,"max_by_price" : {"value" : 39.0}},{"key" : 40.0,"doc_count" : 2,"max_by_price" : {"value" : 54.0}},{"key" : 60.0,"doc_count" : 1,"max_by_price" : {"value" : 69.0}},{"key" : 80.0,"doc_count" : 1,"max_by_price" : {"value" : 99.0}},{"key" : 100.0,"doc_count" : 0,"max_by_price" : {"value" : null}},{"key" : 120.0,"doc_count" : 0,"max_by_price" : {"value" : null}},{"key" : 140.0,"doc_count" : 0,"max_by_price" : {"value" : null}},{"key" : 160.0,"doc_count" : 0,"max_by_price" : {"value" : null}},{"key" : 180.0,"doc_count" : 1,"max_by_price" : {"value" : 198.0}}]}}
}

补充:查询去重

此处语义为:查询前 5 条书籍价格最高的,并按 tag 去重

POST /dying_gq_bookstore/_search
{"size": 5,"collapse": { // 指定去重字段"field": "tag"},"sort": [{"price": {"order": "desc"}}]}

总结

总体来说 ES 的查询 DSL 为我们提供了丰富的语法和聚合语义。

基础查询 使用 query 对应常用查询条件 matchprefixregexptremtremsrange

组合条件 bool 条件连接 mustshouldmust_notfilter 同时配合上述 query 条件进行查询。

聚合分析 aggs 聚合条件 tremsavgsummaxmintop_hitshistogramdate_histogram

这三大类相互 嵌套组合 基本可以覆盖我们绝大多数场景了。更多进阶用法可以到官网进行学习查询。官方文档地址

我是 dying 搁浅 我看了一场 97 小时的电影也没能等来你的点赞关注收藏,我想这不是你不够喜欢我,而是我看的电影不够长……

更多推荐

Elasticsearch 核心查询解决 90% 查询场景

本文发布于:2024-03-04 19:16:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1710167.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:场景   核心   Elasticsearch

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!