add order by goods parameters field sort to aggregation elasticsearch

This commit is contained in:
paulGao 2021-09-01 19:07:30 +08:00
parent 2e80478203
commit 318cc04566
8 changed files with 73 additions and 57 deletions

View File

@ -24,6 +24,7 @@ import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.SearchPage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@ -99,9 +100,9 @@ public class GoodsBuyerController {
@ApiOperation(value = "从ES中获取商品信息")
@GetMapping("/es")
public ResultMessage<Page<EsGoodsIndex>> getGoodsByPageFromEs(EsGoodsSearchDTO goodsSearchParams, PageVO pageVO) {
public ResultMessage<SearchPage<EsGoodsIndex>> getGoodsByPageFromEs(EsGoodsSearchDTO goodsSearchParams, PageVO pageVO) {
pageVO.setNotConvert(true);
Page<EsGoodsIndex> esGoodsIndices = goodsSearchService.searchGoods(goodsSearchParams, pageVO);
SearchPage<EsGoodsIndex> esGoodsIndices = goodsSearchService.searchGoods(goodsSearchParams, pageVO);
return ResultUtil.data(esGoodsIndices);
}

View File

@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
@ -15,7 +16,9 @@ import java.util.List;
*/
@Data
@ApiModel(value = "商品参数分组")
public class GoodsParamsDTO {
public class GoodsParamsDTO implements Serializable {
private static final long serialVersionUID = 4892783539320159200L;
@TableField(value = "group_id")
@ApiModelProperty(value = "分组id")

View File

@ -4,8 +4,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.Serializable;
/**
* 商品参数项
@ -16,7 +15,9 @@ import javax.validation.constraints.Min;
*/
@Data
@ApiModel(value = "商品参数列表")
public class GoodsParamsItemDTO {
public class GoodsParamsItemDTO implements Serializable {
private static final long serialVersionUID = -8823775607604091035L;
@ApiModelProperty(value = "参数ID")
private String paramId;
@ -32,4 +33,7 @@ public class GoodsParamsItemDTO {
@ApiModelProperty(value = "是否必填0 不显示 1 显示")
private Integer required = 0;
@ApiModelProperty(value = "排序")
private Integer sort;
}

View File

@ -9,6 +9,7 @@ import java.io.Serializable;
/**
* 商品属性索引
*
* @author paulG
* @since 2020/10/14
**/
@ -47,11 +48,19 @@ public class EsGoodsAttribute implements Serializable {
@Field(type = FieldType.Text)
private String value;
public EsGoodsAttribute(Integer type,String nameId,String name,String valueId,String value){
this.type=type;
this.nameId=nameId;
this.name=name;
this.valueId=valueId;
this.value=value;
/**
* 排序
*/
@Field(type = FieldType.Integer)
private Integer sort;
public EsGoodsAttribute(Integer type, String nameId, String name, String valueId, String value, Integer sort) {
this.type = type;
this.nameId = nameId;
this.name = name;
this.valueId = valueId;
this.value = value;
this.sort = sort;
}
}

View File

@ -27,7 +27,7 @@ import java.util.Map;
* @author paulG
**/
@Data
@Document(indexName = "#{elasticsearchProperties.indexPrefix}_" + EsSuffix.GOODS_INDEX_NAME)
@Document(indexName = "#{@elasticsearchProperties.indexPrefix}_" + EsSuffix.GOODS_INDEX_NAME)
@ToString
@NoArgsConstructor
public class EsGoodsIndex implements Serializable {
@ -300,6 +300,7 @@ public class EsGoodsIndex implements Serializable {
attribute.setType(1);
attribute.setName(goodsParam.getParamName());
attribute.setValue(goodsParam.getParamValue());
attribute.setSort(goodsParam.getSort());
attributes.add(attribute);
}
}

View File

@ -5,7 +5,7 @@ import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
import cn.lili.modules.search.entity.dto.HotWordsDTO;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.SearchPage;
import java.util.List;
@ -24,7 +24,7 @@ public interface EsGoodsSearchService {
* @param pageVo 分页参数
* @return 搜索结果
*/
Page<EsGoodsIndex> searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo);
SearchPage<EsGoodsIndex> searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo);
/**
* 获取热门关键词

View File

@ -1,7 +1,5 @@
package cn.lili.modules.search.serviceimpl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
@ -30,14 +28,13 @@ import cn.lili.modules.search.service.EsGoodsSearchService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.IterableUtil;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.indices.AnalyzeRequest;
import org.elasticsearch.client.indices.AnalyzeResponse;
import org.elasticsearch.search.SearchHit;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchPage;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
@ -234,14 +231,16 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
*/
@Override
public void updateEsGoodsIndexAllByList(BasePromotion promotion, String key) {
List<EsGoodsIndex> goodsIndices;
List<EsGoodsIndex> goodsIndices = new ArrayList<>();
//如果storeId不为空则表示是店铺活动
if (promotion.getStoreId() != null) {
EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO();
searchDTO.setStoreId(promotion.getStoreId());
//查询出店铺商品
Page<EsGoodsIndex> esGoodsIndices = goodsSearchService.searchGoods(searchDTO, null);
goodsIndices = esGoodsIndices.getContent();
SearchPage<EsGoodsIndex> esGoodsIndices = goodsSearchService.searchGoods(searchDTO, null);
for (SearchHit<EsGoodsIndex> searchHit : esGoodsIndices.getContent()) {
goodsIndices.add(searchHit.getContent());
}
} else {
//否则是平台活动
Iterable<EsGoodsIndex> all = goodsIndexRepository.findAll();
@ -494,16 +493,16 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
}
}
public List<EsGoodsIndex> searchList(String index) {
SearchResponse searchResponse = search(index);
SearchHit[] hits = searchResponse.getHits().getHits();
List<EsGoodsIndex> goodsIndices = new ArrayList<>();
Arrays.stream(hits).forEach(hit -> {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
EsGoodsIndex person = BeanUtil.mapToBean(sourceAsMap, EsGoodsIndex.class, false, CopyOptions.create());
goodsIndices.add(person);
});
return goodsIndices;
}
// public List<EsGoodsIndex> searchList(String index) {
// SearchResponse searchResponse = search(index);
// SearchHit[] hits = searchResponse.getHits().getHits();
// List<EsGoodsIndex> goodsIndices = new ArrayList<>();
// Arrays.stream(hits).forEach(hit -> {
// Map<String, Object> sourceAsMap = hit.getSourceAsMap();
// EsGoodsIndex person = BeanUtil.mapToBean(sourceAsMap, EsGoodsIndex.class, false, CopyOptions.create());
// goodsIndices.add(person);
// });
// return goodsIndices;
// }
}

View File

@ -4,7 +4,6 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.entity.dos.Category;
@ -28,21 +27,19 @@ import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.*;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHitSupport;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.DefaultTypedTuple;
@ -63,6 +60,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
private static final String ATTR_PATH = "attrList";
private static final String ATTR_VALUE = "attrList.value";
private static final String ATTR_NAME = "attrList.name";
private static final String ATTR_SORT = "attrList.sort";
private static final String ATTR_NAME_KEY = "nameList";
private static final String ATTR_VALUE_KEY = "valueList";
@ -90,15 +88,15 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
private Cache cache;
@Override
public Page<EsGoodsIndex> searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo) {
public SearchPage<EsGoodsIndex> searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo) {
if (CharSequenceUtil.isNotEmpty(searchDTO.getKeyword())) {
cache.incrementScore(CachePrefix.HOT_WORD.getPrefix(), searchDTO.getKeyword());
}
NativeSearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder(searchDTO, pageVo, true);
NativeSearchQuery searchQuery = searchQueryBuilder.build();
log.info("searchGoods DSL:{}", searchQuery.getQuery());
return goodsIndexRepository.search(searchQuery);
SearchHits<EsGoodsIndex> search = restTemplate.search(searchQuery, EsGoodsIndex.class);
return SearchHitSupport.searchPageFor(search, searchQuery.getPageable());
}
@Override
@ -106,11 +104,11 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
List<String> hotWords = new ArrayList<>();
// redis 排序中下标从0开始所以这里需要 -1 处理
count = count - 1;
Set<DefaultTypedTuple> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count);
Set<DefaultTypedTuple<Object>> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count);
if (set == null || set.isEmpty()) {
return new ArrayList<String>();
return new ArrayList<>();
}
for (DefaultTypedTuple defaultTypedTuple : set) {
for (DefaultTypedTuple<Object> defaultTypedTuple : set) {
hotWords.add(Objects.requireNonNull(defaultTypedTuple.getValue()).toString());
}
return hotWords;
@ -130,7 +128,8 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
builder.addAggregation(AggregationBuilders.terms("brandAgg").field("brandId").size(Integer.MAX_VALUE));
//参数
AggregationBuilder valuesBuilder = AggregationBuilders.terms("valueAgg").field(ATTR_VALUE);
AggregationBuilder paramsNameBuilder = AggregationBuilders.terms("nameAgg").field(ATTR_NAME).subAggregation(valuesBuilder);
AggregationBuilder sortBuilder = AggregationBuilders.sum("sortAgg").field(ATTR_SORT);
AggregationBuilder paramsNameBuilder = AggregationBuilders.terms("nameAgg").field(ATTR_NAME).subAggregation(sortBuilder).order(BucketOrder.aggregation("sortAgg",false)).subAggregation(valuesBuilder);
builder.addAggregation(AggregationBuilders.nested("attrAgg", ATTR_PATH).subAggregation(paramsNameBuilder));
NativeSearchQuery searchQuery = builder.build();
SearchHits<EsGoodsIndex> search = restTemplate.search(searchQuery, EsGoodsIndex.class);
@ -278,7 +277,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
private NativeSearchQueryBuilder createSearchQueryBuilder(EsGoodsSearchDTO searchDTO, PageVO pageVo, boolean isAggregation) {
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
if (pageVo != null) {
Integer pageNumber = pageVo.getPageNumber() - 1;
int pageNumber = pageVo.getPageNumber() - 1;
if (pageNumber < 0) {
pageNumber = 0;
}
@ -303,7 +302,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
//关键字检索
if (StringUtils.isEmpty(searchDTO.getKeyword())) {
if (CharSequenceUtil.isEmpty(searchDTO.getKeyword())) {
nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
} else {
this.keywordSearch(filterBuilder, queryBuilder, searchDTO.getKeyword(), isAggregation);
@ -331,10 +330,10 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
/**
* 查询属性处理
*
* @param filterBuilder
* @param queryBuilder
* @param searchDTO
* @param isAggregation
* @param filterBuilder 过滤构造器
* @param queryBuilder 查询构造器
* @param searchDTO 查询参数
* @param isAggregation 是否为聚合查询
*/
private void commonSearch(BoolQueryBuilder filterBuilder, BoolQueryBuilder queryBuilder, EsGoodsSearchDTO searchDTO, boolean isAggregation) {
//品牌判定
@ -423,10 +422,10 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
/**
* 关键字查询处理
*
* @param filterBuilder
* @param queryBuilder
* @param keyword
* @param isAggregation
* @param filterBuilder 过滤构造器
* @param queryBuilder 查询构造器
* @param keyword 关键字
* @param isAggregation 是否为聚合查询
*/
private void keywordSearch(BoolQueryBuilder filterBuilder, BoolQueryBuilder queryBuilder, String keyword, boolean isAggregation) {
List<FunctionScoreQueryBuilder.FilterFunctionBuilder> filterFunctionBuilders = new ArrayList<>();