Elasticsearch 5.4.3实战--Java API调用:搜索

ES有多种查询方式,我自己的业务是需要对多个字段进行查询,具体实现类代码如下。

  1 package com.cs99lzzs.elasticsearch.service.imp;
  2
  3 import java.text.DecimalFormat;
  4 import java.util.ArrayList;
  5 import java.util.Iterator;
  6 import java.util.List;
  7 import java.util.Map;
  8
  9 import javax.annotation.Resource;
 10
 11 import org.apache.commons.lang.StringUtils;
 12 import org.apache.log4j.Logger;
 13 import org.apache.lucene.queryparser.classic.QueryParser;
 14 import org.elasticsearch.action.search.SearchRequestBuilder;
 15 import org.elasticsearch.action.search.SearchResponse;
 16 import org.elasticsearch.action.search.SearchType;
 17 import org.elasticsearch.client.Client;
 18 import org.elasticsearch.index.query.BoolQueryBuilder;
 19 import org.elasticsearch.index.query.QueryBuilder;
 20 import org.elasticsearch.index.query.QueryBuilders;
 21 import org.elasticsearch.search.SearchHit;
 22 import org.elasticsearch.search.aggregations.Aggregation;
 23 import org.elasticsearch.search.aggregations.AggregationBuilders;
 24 import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
 25 import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
 26 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
 27 import org.elasticsearch.search.sort.SortBuilder;
 28 import org.elasticsearch.search.sort.SortBuilders;
 29 import org.elasticsearch.search.sort.SortOrder;
 30 import org.elasticsearch.search.suggest.Suggest;
 31 import org.elasticsearch.search.suggest.SuggestBuilder;
 32 import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
 33 import org.springframework.beans.factory.annotation.Value;
 34 import org.springframework.stereotype.Service;
 35
 36 import com.alibaba.fastjson.JSON;
 37 import com.cs99lzzs.elasticsearch.service.ProductSearchService;
 38 import com.cs99lzzs.search.ElasticseachSku;
 39 import com.cs99lzzs.search.EsProductQuery;
 40 import com.cs99lzzs.search.EsResultingSku;
 41 import com.cs99lzzs.search.vo.FacetVO;
 42 import com.cs99lzzs.search.vo.SearchResultVO;
 43
 44 @Service("productSearchService")
 45 public class ProductSearchServiceImp implements ProductSearchService {
 46
 47     private static Logger logger = Logger.getLogger(ProductSearchService.class);
 48
 49     private static String aggrationBrandName = "brand_count";
 50
 51     private static String suggestZhName = "suggestName";
 52
 53     @Resource(name="esClient")
 54     Client esClient;
 55
 56     @Value("${elasticsearch.index}")
 57     private String CLUSTER_INDEX;
 58
 59     @Value("${elasticsearch.type}")
 60     private String CLUSTER_TYPE;
 61
 62
 63     /**
 64      * @return
 65      */
 66     @SuppressWarnings("rawtypes")
 67     @Override
 68     public SearchResultVO get(EsProductQuery esProductQuery) {
 69         if (esProductQuery == null ||
 70                 (StringUtils.isEmpty(esProductQuery.getKeyword())
 71                         && StringUtils.isEmpty(esProductQuery.getCateName())
 72                         && StringUtils.isEmpty(esProductQuery.getBrandName()))) {
 73             return null;
 74         }
 75         //生成搜索条件
 76         QueryBuilder boolQuery = generateBoolQuery(esProductQuery, null);
 77
 78         //浅度分页,越到后面,反应越慢,还有可能导致es崩溃
 79         SearchRequestBuilder srb = esClient.prepareSearch(CLUSTER_INDEX)
 80                 .setTypes(CLUSTER_TYPE)
 81                 .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
 82                 .setQuery(boolQuery)
 83 //                .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))
 84                 .setExplain(true) //explain为true表示根据数据相关度排序,和关键字匹配最高的排在前面
 85                 .setFrom((esProductQuery.getPage() - 1) * esProductQuery.getPageSize())
 86                 .setSize(esProductQuery.getPageSize());
 87
 88         //获取排序规则
 89         SortBuilder sortBuilder = getSortBuilder(esProductQuery);
 90         if (sortBuilder != null) {
 91             srb.addSort(sortBuilder);
 92         }
 93
 94         //按品牌名聚合
 95         TermsAggregationBuilder termAgg = AggregationBuilders.terms(aggrationBrandName).field("brandName");
 96         srb.addAggregation(termAgg);
 97
 98         //执行搜索
 99         SearchResponse actionGet = srb.execute().actionGet();
100
101         //深度分页,推荐实现
102 //        SearchScrollRequestBuilder ssrb = esClient.prepareSearchScroll(actionGet.getScrollId())
103 //                .setScroll(TimeValue.timeValueMinutes(8));
104         //获取查询结果,生成返回对象
105         List<EsResultingSku> skuList = new ArrayList<EsResultingSku>();
106         DecimalFormat priceFormat = new DecimalFormat("#0.00");
107         DecimalFormat discountFormat = new DecimalFormat("#0.0");
108
109         SearchHit[]   hitArray = actionGet.getHits().getHits();
110         for (SearchHit searchHit : hitArray) {
111             ElasticseachSku eSku = JSON.parseObject(searchHit.getSourceAsString(), ElasticseachSku.class);
112             if (eSku != null) {
113                 skuList.add(new EsResultingSku(eSku, discountFormat, priceFormat));
114             }
115         }
116
117         SearchResultVO resultVO = new SearchResultVO();
118         resultVO.setSkus(skuList);
119         //总页数
120         long totalPage = actionGet.getHits().totalHits/esProductQuery.getPageSize();
121         if ((actionGet.getHits().totalHits % esProductQuery.getPageSize()) != 0) {
122             totalPage ++;
123         }
124         resultVO.setTotalPages(totalPage);
125         resultVO.setHits(actionGet.getHits().totalHits);
126         if (skuList.size() > 1) {
127             setFacetVOs(actionGet, resultVO);
128         }
129
130         return resultVO;
131     }
132     /**
133      * @return
134      */
135     @Override
136     public SearchResultVO get(String keyword, int page, int pageSize) {
137         if (StringUtils.isEmpty(keyword)) {
138             return null;
139         }
140
141         //生成搜索条件
142         QueryBuilder boolQuery = generateBoolQuery(null, keyword);
143
144         //浅度分页,越到后面,反应越慢,还有可能导致es崩溃
145         SearchRequestBuilder srb = esClient.prepareSearch(CLUSTER_INDEX)
146                 .setTypes(CLUSTER_TYPE)
147                 .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
148                 .setQuery(boolQuery)
149 //                .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))
150                 .setExplain(true) //explain为true表示根据数据相关度排序,和关键字匹配最高的排在前面
151                 .setFrom((page - 1) * pageSize)
152                 .setSize(pageSize);
153
154         //按品牌名聚合
155         TermsAggregationBuilder termAgg = AggregationBuilders.terms(aggrationBrandName).field("brandName");
156         srb.addAggregation(termAgg);
157
158         //执行搜索
159         SearchResponse actionGet = srb.execute().actionGet();
160
161         //深度分页,推荐实现
162 //        SearchScrollRequestBuilder ssrb = esClient.prepareSearchScroll(actionGet.getScrollId())
163 //                .setScroll(TimeValue.timeValueMinutes(8));
164         //获取查询结果,生成返回对象
165         List<EsResultingSku> skuList = new ArrayList<EsResultingSku>();
166         DecimalFormat priceFormat = new DecimalFormat("#0.00");
167         DecimalFormat discountFormat = new DecimalFormat("#0.0");
168
169         SearchHit[]   hitArray = actionGet.getHits().getHits();
170         for (SearchHit searchHit : hitArray) {
171             ElasticseachSku eSku = JSON.parseObject(searchHit.getSourceAsString(), ElasticseachSku.class);
172             if (eSku != null) {
173                 skuList.add(new EsResultingSku(eSku, discountFormat, priceFormat));
174             }
175         }
176
177         SearchResultVO resultVO = new SearchResultVO();
178         resultVO.setSkus(skuList);
179         //总页数
180         long totalPage = actionGet.getHits().totalHits/pageSize;
181         if ((actionGet.getHits().totalHits % pageSize) != 0) {
182             totalPage ++;
183         }
184         resultVO.setTotalPages(totalPage);
185         resultVO.setHits(actionGet.getHits().totalHits);
186
187
188         return resultVO;
189     }
190
191     /**
192      * @param esProductQuery
193      * @param keyword
194      * @return
195      */
196     private QueryBuilder generateBoolQuery(EsProductQuery esProductQuery, String key) {
197
198         String keyword = null;
199         if (esProductQuery != null && esProductQuery.getKeyword() != null) {
200             keyword = QueryParser.escape(esProductQuery.getKeyword());
201         }
202         if (StringUtils.isNotEmpty(key)) {
203             keyword = QueryParser.escape(key);
204         }
205
206         logger.info("filtered keyword is : " + keyword);
207
208         //其他搜索条件
209         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
210         if (esProductQuery != null) {
211             if (esProductQuery.getIsDelete() == 1) {
212                 boolQueryBuilder.must(QueryBuilders.termQuery("isDelete", true));
213             } else if (esProductQuery.getIsDelete() == -1) {
214                 boolQueryBuilder.must(QueryBuilders.termQuery("isDelete", false));
215             }
216             if (esProductQuery.getSearchable() == 1) {
217                 boolQueryBuilder.must(QueryBuilders.termQuery("searchable", true));
218             } else if (esProductQuery.getIsDelete() == -1) {
219                 boolQueryBuilder.must(QueryBuilders.termQuery("searchable", false));
220             }
221             if (StringUtils.isNotEmpty(esProductQuery.getBrandName())) {
222                 boolQueryBuilder.must(QueryBuilders.termQuery("brandName", QueryParser.escape(esProductQuery.getBrandName())));
223             }
224             if (StringUtils.isNotEmpty(esProductQuery.getCateName())) {
225                 boolQueryBuilder.must(QueryBuilders.termQuery("cateName", QueryParser.escape(esProductQuery.getCateName())));
226             }
227         } else {
228             boolQueryBuilder.must(QueryBuilders.termQuery("isDelete", false));
229             boolQueryBuilder.must(QueryBuilders.termQuery("searchable", true));
230         }
231
232         QueryBuilder multiMatchQuery = null;
233         if (StringUtils.isNotEmpty(keyword)) {
234             multiMatchQuery = QueryBuilders.multiMatchQuery(keyword,
235                     "enName", "zhName","brandZhName", "brandEnName", "aliases", "brandAliases");
236         }
237
238         if (multiMatchQuery == null) {
239             return boolQueryBuilder;
240         } else {
241             return boolQueryBuilder.must(multiMatchQuery);
242         }
243     }
244     /**
245      * @param sortByPrice
246      * @param sortByCommission
247      * @param sortBySalesVolume
248      * @return
249      */
250     @SuppressWarnings("rawtypes")
251     private SortBuilder getSortBuilder(EsProductQuery esProductQuery) {
252         switch (esProductQuery.getSortByPrice()) {
253             case -1:
254                 return SortBuilders.fieldSort("price").order(SortOrder.DESC);
255             case 1:
256                 return SortBuilders.fieldSort("price").order(SortOrder.ASC);
257             default:
258                 break;
259         }
260
261         switch (esProductQuery.getSortByCommission()) {
262             case -1:
263                 return SortBuilders.fieldSort("commission").order(SortOrder.DESC);
264             case 1:
265                 return SortBuilders.fieldSort("commission").order(SortOrder.ASC);
266             default:
267                 break;
268         }
269
270         switch (esProductQuery.getSortByCommission()) {
271             case -1:
272                 return SortBuilders.fieldSort("salesVolume").order(SortOrder.DESC);
273             case 1:
274                 return SortBuilders.fieldSort("salesVolume").order(SortOrder.ASC);
275             default:
276                 break;
277         }
278         return null;
279     }
280
281 }

有什么问题我们可以好好讨论

时间: 2024-10-24 16:12:13

Elasticsearch 5.4.3实战--Java API调用:搜索的相关文章

Elasticsearch 5.4.3实战--Java API调用:搜索建议

通常的搜索引擎,都会根据用户的输入,实时给予匹配的提示. 那么这个功能在elasticsearch中如何实现呢? Elasticsearch里设计了4种类别的Suggester,分别是: Term Suggester Phrase Suggester Completion Suggester Context Suggester 我是采用Completion Suggester来实现的. 原理的文章网上有很多,这里不多说.我们直接上代码: 1 package com.cs99lzzs.elasti

Hbase java API 调用详解

Hbase java API 调用 一. hbase的安装 参考:http://blog.csdn.net/mapengbo521521/article/details/41777721 二.hbase访问方式 Native java api:最常规最高效的访问方式. Hbase shell:hbase的命令行工具,最简单的接口,适合管理员使用 Thrift gateway:利用thrift序列化结束支持各种语言,适合异构系统在线访问 Rest gateway:支持rest风格的http api

spark2.x由浅入深深到底系列六之RDD java api调用scala api的原理

RDD java api其实底层是调用了scala的api来实现的,所以我们有必要对java api是怎么样去调用scala api,我们先自己简单的实现一个scala版本和java版本的RDD和SparkContext 一.简单实现scala版本的RDD和SparkContext class RDD[T](value: Seq[T]) {   //RDD的map操作   def map[U](f: T => U): RDD[U] = {     new RDD(value.map(f))   

elasticsearch java API 实现搜索样例

查看cluster.version:curl 'centos1:9200'插入:curl -XPUT 'http://localhost:9200/dept/employee/1' -d '{ "empname": "emp1"}'查看index:curl 'centos1:9200/_cat/indices?v'查看1条内容:curl 'centos1:9200/dept/employee/1?pretty'查看所有内容:curl 'centos1:9200/de

Elasticsearch java api 基本搜索部分详解

版权声明:本文非原创文章,转载出处:http://blog.csdn.net/molong1208/article/details/50512149 一.所使用版本的介绍 使用的是elasticsearch2.1.0版本,在此只是简单介绍搜索部分的api使用 二.简单的搜索 使用api的时候,基本上可以将DSL搜索的所有情况均写出来,在此给出一个最简单搜索的全部的过程以及代码,之后将对不同的搜索只是针对函数进行介绍 (1)DSL搜索 对于最简单的DSL搜索,对一个词进行搜索使用url直接进行通信

ElasticSearch(十二) Bool Query JAVA API

Bool Query 用于组合多个叶子或复合查询子句的默认查询 must 相当于 与 & = must not 相当于 非 ~   != should 相当于 或  |   or  filter  过滤 boolQuery() .must(termQuery("content", "test1")) .must(termQuery("content", "test4")) .mustNot(termQuery(&quo

Elasticsearch 5.1.1搜索高亮及Java API实现

5.1.1的搜索高亮和2.X有所变化,但是变化不大.下面分四步来介绍:创建索引(设置mapping/IK分词).索引文档.REST API的搜索高亮.JAVA API的搜索高亮. 注:从这篇博客开始,采用简写的代码风格,也就是Sence插件或者kibana的dev tools中采用的风格.(温馨提示:安装kibana 5.1.1,在dev tools中直接可以使用简单格式命令.) 一.创建索引 文档结构为blog/article/id.先创建一个空的index: PUT blog 创建mappi

大数据技术之_20_Elasticsearch学习_01_概述 + 快速入门 + Java API 操作 + 创建、删除索引 + 新建、搜索、更新删除文档 + 条件查询 + 映射操作

一 概述1.1 什么是搜索?1.2 如果用数据库做搜索会怎么样?1.3 什么是全文检索和 Lucene?1.4 什么是 Elasticsearch?1.5 Elasticsearch 的适用场景1.6 Elasticsearch 的特点1.7 Elasticsearch 的核心概念1.7.1 近实时1.7.2 Cluster(集群)1.7.3 Node(节点)1.7.4 Index(索引 --> 数据库)1.7.5 Type(类型 --> 表)1.7.6 Document(文档 -->

ElasticSearch Java Api -创建索引

ElasticSearch JAVA API官网文档:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-index.html 一.生成JSON 创建索引的第一步是要把对象转换为JSON字符串.官网给出了四种创建JSON文档的方法: 1.1手写方式生成 String json = "{" + "\"user\":\"kimchy\"