首页 > 代码库 > Elasticsearch 5.4.3实战--Java API调用:搜索

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 }

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

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