ES有多种查询方式,我自己的业务是需要对多个字段进行查询,具体实现类代码如下。
package com.cs99lzzs.elasticsearch.service.imp; import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import javax.annotation.Resource; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSON;
import com.cs99lzzs.elasticsearch.service.ProductSearchService;
import com.cs99lzzs.search.ElasticseachSku;
import com.cs99lzzs.search.EsProductQuery;
import com.cs99lzzs.search.EsResultingSku;
import com.cs99lzzs.search.vo.FacetVO;
import com.cs99lzzs.search.vo.SearchResultVO; @Service("productSearchService")
public class ProductSearchServiceImp implements ProductSearchService { private static Logger logger = Logger.getLogger(ProductSearchService.class); private static String aggrationBrandName = "brand_count"; private static String suggestZhName = "suggestName"; @Resource(name="esClient")
Client esClient; @Value("${elasticsearch.index}")
private String CLUSTER_INDEX; @Value("${elasticsearch.type}")
private String CLUSTER_TYPE; /**
* @return
*/
@SuppressWarnings("rawtypes")
@Override
public SearchResultVO get(EsProductQuery esProductQuery) {
if (esProductQuery == null ||
(StringUtils.isEmpty(esProductQuery.getKeyword())
&& StringUtils.isEmpty(esProductQuery.getCateName())
&& StringUtils.isEmpty(esProductQuery.getBrandName()))) {
return null;
}
//生成搜索条件
QueryBuilder boolQuery = generateBoolQuery(esProductQuery, null); //浅度分页,越到后面,反应越慢,还有可能导致es崩溃
SearchRequestBuilder srb = esClient.prepareSearch(CLUSTER_INDEX)
.setTypes(CLUSTER_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQuery)
// .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))
.setExplain(true) //explain为true表示根据数据相关度排序,和关键字匹配最高的排在前面
.setFrom((esProductQuery.getPage() - 1) * esProductQuery.getPageSize())
.setSize(esProductQuery.getPageSize()); //获取排序规则
SortBuilder sortBuilder = getSortBuilder(esProductQuery);
if (sortBuilder != null) {
srb.addSort(sortBuilder);
} //按品牌名聚合
TermsAggregationBuilder termAgg = AggregationBuilders.terms(aggrationBrandName).field("brandName");
srb.addAggregation(termAgg); //执行搜索
SearchResponse actionGet = srb.execute().actionGet(); //深度分页,推荐实现
// SearchScrollRequestBuilder ssrb = esClient.prepareSearchScroll(actionGet.getScrollId())
// .setScroll(TimeValue.timeValueMinutes(8));
//获取查询结果,生成返回对象
List<EsResultingSku> skuList = new ArrayList<EsResultingSku>();
DecimalFormat priceFormat = new DecimalFormat("#0.00");
DecimalFormat discountFormat = new DecimalFormat("#0.0"); SearchHit[] hitArray = actionGet.getHits().getHits();
for (SearchHit searchHit : hitArray) {
ElasticseachSku eSku = JSON.parseObject(searchHit.getSourceAsString(), ElasticseachSku.class);
if (eSku != null) {
skuList.add(new EsResultingSku(eSku, discountFormat, priceFormat));
}
} SearchResultVO resultVO = new SearchResultVO();
resultVO.setSkus(skuList);
//总页数
long totalPage = actionGet.getHits().totalHits/esProductQuery.getPageSize();
if ((actionGet.getHits().totalHits % esProductQuery.getPageSize()) != 0) {
totalPage ++;
}
resultVO.setTotalPages(totalPage);
resultVO.setHits(actionGet.getHits().totalHits);
if (skuList.size() > 1) {
setFacetVOs(actionGet, resultVO);
} return resultVO;
}
/**
* @return
*/
@Override
public SearchResultVO get(String keyword, int page, int pageSize) {
if (StringUtils.isEmpty(keyword)) {
return null;
} //生成搜索条件
QueryBuilder boolQuery = generateBoolQuery(null, keyword); //浅度分页,越到后面,反应越慢,还有可能导致es崩溃
SearchRequestBuilder srb = esClient.prepareSearch(CLUSTER_INDEX)
.setTypes(CLUSTER_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQuery)
// .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))
.setExplain(true) //explain为true表示根据数据相关度排序,和关键字匹配最高的排在前面
.setFrom((page - 1) * pageSize)
.setSize(pageSize); //按品牌名聚合
TermsAggregationBuilder termAgg = AggregationBuilders.terms(aggrationBrandName).field("brandName");
srb.addAggregation(termAgg); //执行搜索
SearchResponse actionGet = srb.execute().actionGet(); //深度分页,推荐实现
// SearchScrollRequestBuilder ssrb = esClient.prepareSearchScroll(actionGet.getScrollId())
// .setScroll(TimeValue.timeValueMinutes(8));
//获取查询结果,生成返回对象
List<EsResultingSku> skuList = new ArrayList<EsResultingSku>();
DecimalFormat priceFormat = new DecimalFormat("#0.00");
DecimalFormat discountFormat = new DecimalFormat("#0.0"); SearchHit[] hitArray = actionGet.getHits().getHits();
for (SearchHit searchHit : hitArray) {
ElasticseachSku eSku = JSON.parseObject(searchHit.getSourceAsString(), ElasticseachSku.class);
if (eSku != null) {
skuList.add(new EsResultingSku(eSku, discountFormat, priceFormat));
}
} SearchResultVO resultVO = new SearchResultVO();
resultVO.setSkus(skuList);
//总页数
long totalPage = actionGet.getHits().totalHits/pageSize;
if ((actionGet.getHits().totalHits % pageSize) != 0) {
totalPage ++;
}
resultVO.setTotalPages(totalPage);
resultVO.setHits(actionGet.getHits().totalHits); return resultVO;
} /**
* @param esProductQuery
* @param keyword
* @return
*/
private QueryBuilder generateBoolQuery(EsProductQuery esProductQuery, String key) { String keyword = null;
if (esProductQuery != null && esProductQuery.getKeyword() != null) {
keyword = QueryParser.escape(esProductQuery.getKeyword());
}
if (StringUtils.isNotEmpty(key)) {
keyword = QueryParser.escape(key);
} logger.info("filtered keyword is : " + keyword); //其他搜索条件
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (esProductQuery != null) {
if (esProductQuery.getIsDelete() == 1) {
boolQueryBuilder.must(QueryBuilders.termQuery("isDelete", true));
} else if (esProductQuery.getIsDelete() == -1) {
boolQueryBuilder.must(QueryBuilders.termQuery("isDelete", false));
}
if (esProductQuery.getSearchable() == 1) {
boolQueryBuilder.must(QueryBuilders.termQuery("searchable", true));
} else if (esProductQuery.getIsDelete() == -1) {
boolQueryBuilder.must(QueryBuilders.termQuery("searchable", false));
}
if (StringUtils.isNotEmpty(esProductQuery.getBrandName())) {
boolQueryBuilder.must(QueryBuilders.termQuery("brandName", QueryParser.escape(esProductQuery.getBrandName())));
}
if (StringUtils.isNotEmpty(esProductQuery.getCateName())) {
boolQueryBuilder.must(QueryBuilders.termQuery("cateName", QueryParser.escape(esProductQuery.getCateName())));
}
} else {
boolQueryBuilder.must(QueryBuilders.termQuery("isDelete", false));
boolQueryBuilder.must(QueryBuilders.termQuery("searchable", true));
} QueryBuilder multiMatchQuery = null;
if (StringUtils.isNotEmpty(keyword)) {
multiMatchQuery = QueryBuilders.multiMatchQuery(keyword,
"enName", "zhName","brandZhName", "brandEnName", "aliases", "brandAliases");
} if (multiMatchQuery == null) {
return boolQueryBuilder;
} else {
return boolQueryBuilder.must(multiMatchQuery);
}
}
/**
* @param sortByPrice
* @param sortByCommission
* @param sortBySalesVolume
* @return
*/
@SuppressWarnings("rawtypes")
private SortBuilder getSortBuilder(EsProductQuery esProductQuery) {
switch (esProductQuery.getSortByPrice()) {
case -1:
return SortBuilders.fieldSort("price").order(SortOrder.DESC);
case 1:
return SortBuilders.fieldSort("price").order(SortOrder.ASC);
default:
break;
} switch (esProductQuery.getSortByCommission()) {
case -1:
return SortBuilders.fieldSort("commission").order(SortOrder.DESC);
case 1:
return SortBuilders.fieldSort("commission").order(SortOrder.ASC);
default:
break;
} switch (esProductQuery.getSortByCommission()) {
case -1:
return SortBuilders.fieldSort("salesVolume").order(SortOrder.DESC);
case 1:
return SortBuilders.fieldSort("salesVolume").order(SortOrder.ASC);
default:
break;
}
return null;
} }
有什么问题我们可以好好讨论