ElasticSearch进阶:多种查询操作,各种ES查询以及在Java中的实现

目录

前言

1 词条查询

1.1 等值查询-term

1.2 多值查询-terms

1.3 范围查询-range

1.4 前缀查询-prefix

1.5 通配符查询-wildcard

2 复合查询

2.1 布尔查询

2.2 Filter查询

3 聚合查询

3.1 最值、平均值、求和

3.2 去重查询

3.3 分组聚合

3.3.1 单条件分组

3.3.2 多条件分组

3.4 过滤聚合


前言

  • ElasticSearch第一篇:ElasticSearch基础:从倒排索引说起,快速认知ES

这篇博文的主题是ES的查询,因此我整理了尽可能齐全的ES查询场景,形成下面的图:

在这里插入图片描述

本文基于elasticsearch 7.13.2版本,es从7.0以后,发生了很大的更新。7.3以后,已经不推荐使用TransportClient这个client,取而代之的是Java High Level REST Client

测试使用的数据示例

首先是,Mysql中的部分测试数据:

id name age sex address sect skill power create_time modify_time
1 张无忌 18 光明顶 明教 九阳神功 99 2021-05-14 16:50:33 2021-06-29 16:48:56
2 周芷若 17 峨眉山 峨嵋派 九阴真经 88 2021-05-14 11:37:07 2021-06-29 16:56:40
3 赵敏 14 大都 朝廷 40 2021-05-14 11:37:07 2021-06-29 15:22:24

Mysql中的一行数据在ES中以一个文档形式存在:

 {
   "_index" : "person",
   "_type" : "_doc",
   "_id" : "4",
   "_score" : 1.0,
   "_source" : {
     "address" : "峨眉山",
     "modifyTime" : "2021-06-29 19:46:25",
     "createTime" : "2021-05-14 11:37:07",
     "sect" : "峨嵋派",
     "sex" : "男",
     "skill" : "降龙十八掌",
     "name" : "宋青书",
     "id" : 4,
     "power" : 50,
     "age" : 21
   }
 }

简单梳理了一下ES JavaAPI的相关体系,感兴趣的可以自己研读一下源码。

在这里插入图片描述

接下来,我们用十几个实例,迅速上手ES的查询操作,每个示例将提供SQL语句、ES语句和Java代码。

1 词条查询

所谓词条查询,也就是ES不会对查询条件进行分词处理,只有当词条和查询字符串完全匹配时,才会被查询到。

1.1 等值查询-term

等值查询,即筛选出一个字段等于特定值的所有记录。

SQL:

select * from person where name = '张无忌';

而使用ES查询语句却很不一样(注意查询字段带上keyword):

 GET /person/_search
 {
     "query": {
         "term": {
             "name.keyword": {
                 "value": "张无忌",
                 "boost": 1.0
             }
         }
     }
 }

ElasticSearch 5.0以后,string类型有重大变更,移除了string类型,string字段被拆分成两种新的数据类型: text用于全文搜索的,而keyword用于关键词搜索。

查询结果:

 {
   "took" : 0,
   "timed_out" : false,
   "_shards" : { // 分片信息
     "total" : 1, // 总计分片数
     "successful" : 1, // 查询成功的分片数
     "skipped" : 0, // 跳过查询的分片数
     "failed" : 0  // 查询失败的分片数
   },
   "hits" : { // 命中结果
     "total" : {
       "value" : 1, // 数量
       "relation" : "eq"  // 关系:等于
     },
     "max_score" : 2.8526313,  // 最高分数
     "hits" : [
       {
         "_index" : "person", // 索引
         "_type" : "_doc", // 类型
         "_id" : "1",
         "_score" : 2.8526313,
         "_source" : {
           "address" : "光明顶",
           "modifyTime" : "2021-06-29 16:48:56",
           "createTime" : "2021-05-14 16:50:33",
           "sect" : "明教",
           "sex" : "男",
           "skill" : "九阳神功",
           "name" : "张无忌",
           "id" : 1,
           "power" : 99,
           "age" : 18
         }
       }
     ]
   }
 }

Java中构造ES请求的方式:(后续例子中只保留SearchSourceBuilder的构建语句)

 /**
  * term精确查询
  *
  * @throws IOException
  */
 ​
 @Autowired
 private RestHighLevelClient client;
 ​
 @Test
 public void queryTerm() throws IOException {
     // 根据索引创建查询请求
     SearchRequest searchRequest = new SearchRequest("person");
     SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
     // 构建查询语句
     searchSourceBuilder.query(QueryBuilders.termQuery("name.keyword", "张无忌"));
     System.out.println("searchSourceBuilder===================" + searchSourceBuilder);
     searchRequest.source(searchSourceBuilder);
     SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
     System.out.println(JSONObject.toJSON(response));
 }

仔细观察查询结果,会发现ES查询结果中会带有_score这一项,ES会根据结果匹配程度进行评分。打分是会耗费性能的,如果确认自己的查询不需要评分,就设置查询语句关闭评分:

 GET /person/_search
 {
     "query": {
         "constant_score": {
             "filter": {
                 "term": {
                     "sect.keyword": {
                         "value": "张无忌",
                         "boost": 1.0
                     }
                 }
             },
             "boost": 1.0
         }
     }
 }

Java构建查询语句:

 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
 // 这样构造的查询条件,将不进行score计算,从而提高查询效率
 searchSourceBuilder.query(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("sect.keyword", "明教")));

1.2 多值查询-terms

多条件查询类似Mysql里的IN查询,例如:

 select * from persons where sect in('明教','武当派');

ES查询语句:

 GET /person/_search
 {
     "query": {
         "terms": {
             "sect.keyword": [
                 "明教",
                 "武当派"
             ],
             "boost": 1.0
         }
     }
 }

Java实现:

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Elasticsearch 使用深度分页功能需要注意以下几点: 1. 尽量避免使用深度分页功能,因为它会增加网络和计算开销,可能导致性能问题。 2. 深度分页功能是通过设置 from 和 size 参数来实现的。from 参数表示从哪个位置开始查询,size 参数表示每页返回的文档数量。 3. Elasticsearch 默认最多只能返回 10000 条记录,如果需要查询更多的记录,需要设置 index.max_result_window 参数。但是设置太大会占用过多的内存,影响性能。 下面是一个 Java 实现 Elasticsearch 分页查询的示例代码: ``` import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.Client; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; public class ESQuery { private Client client; public ESQuery(Client client) { this.client = client; } public void search(String index, String type, int from, int size) { SearchResponse response = client.prepareSearch(index) .setTypes(type) .setQuery(QueryBuilders.matchAllQuery()) .addSort(SortBuilders.fieldSort("_id").order(SortOrder.DESC)) .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setFrom(from) .setSize(size) .execute() .actionGet(); SearchHits hits = response.getHits(); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); } } } ``` 调用示例: ``` ESQuery esQuery = new ESQuery(client); esQuery.search("my_index", "my_type", 0, 10); // 查询第一页,每页10条记录 esQuery.search("my_index", "my_type", 10, 10); // 查询第二页,每页10条记录,从第11条记录开始 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值