zoukankan      html  css  js  c++  java
  • 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 }

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

  • 相关阅读:
    用迁移学习创造的通用语言模型ULMFiT,达到了文本分类的最佳水平
    论文分享|《Universal Language Model Fine-tuning for Text Classificatio》
    tesnorflow实现N个epoch训练数据读取的办法
    理解TensorFlow的Queue
    tensorflow基本操作介绍
    前端框架 Vue 初探
    LeetCode 292 Nim Game(Nim游戏)
    设计模式有感
    说说翻转的数据结构课
    java 中xml转换为json对象
  • 原文地址:https://www.cnblogs.com/cs99lzzs/p/7212542.html
Copyright © 2011-2022 走看看