ES在企业项目中的实战总结,彻底掌握ES的使用
最佳答案 问答题库558位专家为你答疑解惑
通过之前两篇文章
- 了解了ES的核心概念和基础使用
- 学习进阶的DSL语法处理复杂的查询
这段时间通过在本企业代码中对ES框架的使用,总结了不少经验。主要分为三点
- 企业封装了ES原生的api,需要使用企业项目提供的接口实现 -------简单使用(本章节目的)
- 项目会遇到更复杂的查询需求,需要进一步深入对ES的学习 -------复杂使用
- 了解项目如何封装原生的api,学习设计思想 --------深入学习
目录
- 1. Term查询
- 1.1 原生api实现term查询
- 1.2 企业api实现term查询
- 2. 复合查询__must
- 2.1 原生api实现must查询
- 2.2 企业api实现must查询
- 3. 复合查询__should
- 4. 复合查询__mustnot
- 5. 分页和排序
- 5.1 原生api实现分页和排序
- 5.2 企业api实现分页和排序
- 6 聚合查询
- 6.1 原生api实现桶聚合
- 6.2 企业api实现桶聚合
------------------------------本章节核心目的是梳理出 本企业项目提供的api 和 原生ES提供的api 的使用区别--------------------------------
本企业将ES的api大致封装成了两个核心类
EsOperater类
EsOperaterBuiler类(重点关注)
1. Term查询
1.1 原生api实现term查询
@Test
void TermQuery(){// 获取client这里默认已经获取// 1. 准备request (参数为索引名称)SearchRequest request = new SearchRequest("indexName");// 2. 构建DSL// 2.1 获取建造者SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 2.2 建造者调用DSLsearchSourceBuilder.termQuery("name","zjh");// 2.3 组装request.source(searchSourceBuilder);// 3. 发送请求SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
此时就可以获取到source的数据了。上述写法也可以简化,如下
// 此方式常用
@Test
void TermQuery(){// 获取client这里默认已经获取// 1. 准备request (参数为索引名称)SearchRequest request = new SearchRequest("indexName");// 2. 构建DSL语句request.source().query(QueryBuilders.termQuery("name","zjh"));// 3. 发送请求SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
1.2 企业api实现term查询
@Test
void TermQuery(){// 构建索引名称String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;// 1. 设置索引集合EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);// 2. 设置查询构建器 + 准备DSL语句builder.queryBuilder(QueryBuilders.termQuery("name","zjh"));// 3. 发送请求SearchResponse response = builder.build().execute();// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
解释:
步骤一:需要将 索引名 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用
步骤二:需要将 DSL语句 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用
步骤三:需要从esOperaterBuiler类 切换到 esOperater类,再执行最核心的 execute() 方法,这个方法会进行一些列操作,将最终的结果返回给 response
2. 复合查询__must
2.1 原生api实现must查询
@Test
void MustQuery(){// 获取client这里默认已经获取// 1. 准备request (参数为索引名称)SearchRequest request = new SearchRequest("indexName");// 2. 构建DSL语句// 2.1 创建bool查询BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 2.2 添加must条件boolQuery.must(QueryBuilders.termQuery("name", "zjh"));// 2.3 构建请求内容request.source().query(boolQuery);// 3. 发送请求SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
2.2 企业api实现must查询
@Test
void TermQuery(){// 构建索引名称String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;// 1. 设置索引集合EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);// 2. 设置查询构建器 + 准备DSL语句// 2.1 创建bool查询BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 2.2 添加must条件boolQuery.must(QueryBuilders.termQuery("name", "zjh"));// 此行代码的作用就是将构造的must条件,存放到EsOperater类的全局变量builder.queryBuilder(boolQuery);// 3. 发送请求SearchResponse response = builder.build().execute();// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
解释一下步骤二:可能会疑惑为什么不这样写BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();BoolQueryBuilder mustQuery = boolQuery.must(QueryBuilders.termQuery("name", "zjh"));builder.queryBuilder(mustQuery);因为must(参数)底层会将参数传给boolQuery.must()的boolQuery对象,是递增的逻辑
解释:
步骤一:需要将 索引名 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用
步骤二:需要将 DSL语句(布尔查询) 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用
步骤三:需要从esOperaterBuiler类 切换到 esOperater类,再执行最核心的 execute() 方法,这个方法会进行一些列操作,将最终的结果返回给 response
可以进一步简化
@Test
void TermQuery(){// 构建索引名称String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;// DSL语句BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();boolQuery.must(QueryBuilders.termQuery("name", "zjh"));// 使用企业api实现查询EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler();SearchResponse response = builder.index(indexName).queryBuilder(boolQuery).build().execute();// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
3. 复合查询__should
同理
4. 复合查询__mustnot
同理
5. 分页和排序
5.1 原生api实现分页和排序
// 此方式常用
@Test
void TermQuery(){// 获取client这里默认已经获取// 1. 准备request (参数为索引名称)SearchRequest request = new SearchRequest("indexName");//2.查询__构建DSL语句request.source().query(QueryBuilders.termQuery("name","zjh"));// 分页request.source().from.size(5);// 时间排序request.source().sort(“logTime”,SortOrder.ASC);// 3. 发送请求SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
5.2 企业api实现分页和排序
@Test
void TermQuery(){// 构建索引名称String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;// 1. 设置索引集合EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);// 2. 查询builder.queryBuilder(QueryBuilders.termQuery("name","zjh"));// 分页builder.queryBuilder(QueryBuilders.termQuery("name","zjh")).size(5);// 排序builder.queryBuilder(QueryBuilders.termQuery("name","zjh")).sort("logTime").sortOrder(SortOrder.DESC);// 3. 发送请求SearchResponse response = builder.build().execute();// 4. 解析数据,得到_source数据SearchHit[] hits = response.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}
6 聚合查询
6.1 原生api实现桶聚合
// 需求:实现对城市、品牌的聚合。即用户输入城市、品牌,得到搜索结果
@Test
void TermQuery(){// 获取client这里默认已经获取// 1. 准备request (参数为索引名称)SearchRequest request = new SearchRequest("indexName");//2.查询// CityName:自定义桶名; city:根据城市聚合AggregationBuilder aggregationBuilder1 = AggregationBuilders.terms("CityName").field("city");AggregationBuilder aggregationBuilder2 = AggregationBuilders.terms("BrandName").field("brand");request.source().aggregation(aggregationBuilder1);request.source().aggregation(aggregationBuilder2);// 3. 发送请求SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);// 4. 解析数据Aggreagtions aggreagtions = response.getAggreagtions();List<? extends Terms.Bucket> buckets1 = aggreagtions.get("CityName").getBuckets();for (Terms.Bucket bucket : buckets) {//打印结果是:西安 或者 上海System.out.println(bucket.getKeyAsString());}List<? extends Terms.Bucket> buckets2 = aggreagtions.get("BrandName").getBuckets();for (Terms.Bucket bucket : buckets) {//打印结果是:星巴克 或者 瑞幸System.out.println(bucket.getKeyAsString());}}
6.2 企业api实现桶聚合
// 需求:实现对城市、品牌的聚合。即用户输入城市、品牌,得到搜索结果
@Test
void TermQuery(){// 获取client这里默认已经获取// 1. 准备request (参数为索引名称)SearchRequest request = new SearchRequest("indexName");//2.查询List<AggregationBuilder> aggregationBuilderList = new ArrayList<>();aggregationBuilderList.add(AggregationBuilders.terms("CityName").field("city"));;aggregationBuilderList.add(AggregationBuilders.terms("BrandName").field("brand"));// aggBuilderList()企业封装的工具,将聚合参数赋值到全局变量上builder.aggBuilderList(aggregationBuilderList);// 3. 发送请求SearchResponse response = builder.size(1).build().execute();// 4. 解析数据Aggreagtions aggreagtions = response.getAggreagtions();// 注意ParsedStringTerms,还有ParsedLongTerms、ParsedDoubleTerms...ParsedStringTerms CityName = aggreagtions.get("CityName");for (Terms.Bucket bucket : CityName.getBuckets()) {//打印结果是:西安 或者 上海System.out.println(bucket.getKeyAsString());}ParsedStringTerms BrandName = aggreagtions.get("BrandName");for (Terms.Bucket bucket : BrandName.getBuckets()) {//打印结果是:星巴克 或者 瑞幸System.out.println(bucket.getKeyAsString());}}
这里需要解释一下步骤四中的 ParsedStringTerms
ES会将聚合结果封装到特定的类中,方便你来处理不同类型的聚合结果。
ParsedLongTerms
:
- 这个类用于处理长整型(long)类型的聚合结果。
ParsedStringTerms
:
- 这个类用于处理字符串(String)类型的聚合结果。
什么意思呢?在ES中对"CityName"进行聚合。
返回结果中可以看到如下信息,表示星巴克有三家(西安)
key:“星巴克” (字符串类型)
doc_count : 3 (long类型)
因此根据key的类型,正确选择使用ParsedStringTerms || ParsedLongTerms ||…接收聚合结果,否则报错。
示例图:
99%的人还看了
相似问题
猜你感兴趣
版权申明
本文"ES在企业项目中的实战总结,彻底掌握ES的使用":http://eshow365.cn/6-24472-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!