!49 优化商品搜索(增加商品基础分数,同goodsId递减。增加销量分数占比)
Merge pull request !49 from OceansDeep/feature/pg
This commit is contained in:
commit
3dd61f47fc
@ -288,9 +288,11 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
* @param goodsSkuList 商品sku信息
|
||||
*/
|
||||
private void generatorGoodsIndex(Goods goods, List<GoodsSku> goodsSkuList) {
|
||||
int skuSource = 100;
|
||||
for (GoodsSku goodsSku : goodsSkuList) {
|
||||
EsGoodsIndex esGoodsOld = goodsIndexService.findById(goodsSku.getId());
|
||||
EsGoodsIndex goodsIndex = this.settingUpGoodsIndexData(goods, goodsSku);
|
||||
goodsIndex.setSkuSource(skuSource--);
|
||||
//如果商品库存不为0,并且es中有数据
|
||||
if (goodsSku.getQuantity() > 0 && esGoodsOld == null) {
|
||||
log.info("生成商品索引 {}", goodsIndex);
|
||||
|
@ -197,6 +197,9 @@ public abstract class BaseElasticsearchService {
|
||||
" \"commentNum\": {\n" +
|
||||
" \"type\": \"long\"\n" +
|
||||
" },\n" +
|
||||
" \"skuSource\": {\n" +
|
||||
" \"type\": \"long\"\n" +
|
||||
" },\n" +
|
||||
" \"goodsId\": {\n" +
|
||||
" \"type\": \"text\",\n" +
|
||||
" \"fields\": {\n" +
|
||||
|
@ -126,7 +126,7 @@ public class Goods extends BaseEntity {
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否为推荐商品", required = true)
|
||||
private boolean recommend;
|
||||
private Boolean recommend;
|
||||
|
||||
@ApiModelProperty(value = "销售模式", required = true)
|
||||
private String salesModel;
|
||||
|
@ -1,13 +1,14 @@
|
||||
package cn.lili.modules.goods.entity.dos;
|
||||
|
||||
import cn.lili.mybatis.BaseEntity;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
|
||||
import cn.lili.mybatis.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
@ -19,6 +20,7 @@ import java.util.Date;
|
||||
* @author pikachu
|
||||
* @since 2020-02-23 9:14:33
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("li_goods_sku")
|
||||
@ApiModel(value = "商品sku对象")
|
||||
@ -146,7 +148,7 @@ public class GoodsSku extends BaseEntity {
|
||||
private String goodsVideo;
|
||||
|
||||
@ApiModelProperty(value = "是否为推荐商品", required = true)
|
||||
private boolean recommend;
|
||||
private Boolean recommend;
|
||||
|
||||
@ApiModelProperty(value = "销售模式", required = true)
|
||||
private String salesModel;
|
||||
|
@ -587,6 +587,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
sku.setStoreName(goods.getStoreName());
|
||||
sku.setStoreCategoryPath(goods.getStoreCategoryPath());
|
||||
sku.setFreightTemplateId(goods.getTemplateId());
|
||||
sku.setRecommend(goods.getRecommend());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,19 +63,20 @@ public class ParametersServiceImpl extends ServiceImpl<ParametersMapper, Paramet
|
||||
queryWrapper.like(Goods::getParams, parameters.getGroupId());
|
||||
List<Map<String, Object>> goodsList = this.goodsService.listMaps(queryWrapper);
|
||||
|
||||
for (Map<String, Object> goods : goodsList) {
|
||||
String params = (String) goods.get("params");
|
||||
List<GoodsParamsDTO> goodsParamsDTOS = JSONUtil.toList(params, GoodsParamsDTO.class);
|
||||
List<GoodsParamsDTO> goodsParamsDTOList = goodsParamsDTOS.stream().filter(i -> i.getGroupId() != null && i.getGroupId().equals(parameters.getGroupId())).collect(Collectors.toList());
|
||||
this.setGoodsItemDTOList(goodsParamsDTOList, parameters);
|
||||
this.goodsService.updateGoodsParams(goods.get("id").toString(), JSONUtil.toJsonStr(goodsParamsDTOS));
|
||||
goodsIds.add(goods.get("id").toString());
|
||||
if (!goodsList.isEmpty()) {
|
||||
for (Map<String, Object> goods : goodsList) {
|
||||
String params = (String) goods.get("params");
|
||||
List<GoodsParamsDTO> goodsParamsDTOS = JSONUtil.toList(params, GoodsParamsDTO.class);
|
||||
List<GoodsParamsDTO> goodsParamsDTOList = goodsParamsDTOS.stream().filter(i -> i.getGroupId() != null && i.getGroupId().equals(parameters.getGroupId())).collect(Collectors.toList());
|
||||
this.setGoodsItemDTOList(goodsParamsDTOList, parameters);
|
||||
this.goodsService.updateGoodsParams(goods.get("id").toString(), JSONUtil.toJsonStr(goodsParamsDTOS));
|
||||
goodsIds.add(goods.get("id").toString());
|
||||
}
|
||||
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX.name();
|
||||
//发送mq消息
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIds), RocketmqSendCallbackBuilder.commonCallback());
|
||||
}
|
||||
|
||||
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX.name();
|
||||
//发送mq消息
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIds), RocketmqSendCallbackBuilder.commonCallback());
|
||||
return this.updateById(parameters);
|
||||
}
|
||||
|
||||
|
@ -259,6 +259,12 @@ public class EsGoodsIndex implements Serializable {
|
||||
@ApiModelProperty(value = "商品类型", required = true)
|
||||
private String goodsType;
|
||||
|
||||
/**
|
||||
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
|
||||
*/
|
||||
@ApiModelProperty(value = "商品sku基础分数", required = true)
|
||||
private Integer skuSource;
|
||||
|
||||
/**
|
||||
* 商品属性(参数和规格)
|
||||
*/
|
||||
@ -289,7 +295,7 @@ public class EsGoodsIndex implements Serializable {
|
||||
this.categoryPath = sku.getCategoryPath();
|
||||
this.goodsVideo = sku.getGoodsVideo();
|
||||
this.mobileIntro = sku.getMobileIntro();
|
||||
this.buyCount = sku.getBuyCount();
|
||||
this.buyCount = sku.getBuyCount() != null ? sku.getBuyCount() : 0;
|
||||
this.commentNum = sku.getCommentNum();
|
||||
this.small = sku.getSmall();
|
||||
this.brandId = sku.getBrandId();
|
||||
@ -302,6 +308,7 @@ public class EsGoodsIndex implements Serializable {
|
||||
this.isAuth = sku.getIsAuth();
|
||||
this.intro = sku.getIntro();
|
||||
this.grade = sku.getGrade();
|
||||
this.recommend = sku.getRecommend();
|
||||
this.releaseTime = new Date();
|
||||
}
|
||||
}
|
||||
|
@ -126,48 +126,30 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
|
||||
queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name());
|
||||
queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
|
||||
|
||||
List<GoodsSku> list = goodsSkuService.list(queryWrapper);
|
||||
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
|
||||
//库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量
|
||||
for (GoodsSku goodsSku : list) {
|
||||
Goods goods = goodsService.getById(goodsSku.getGoodsId());
|
||||
//如果出现极端情况,有sku,没有与之匹配的商品,则跳过
|
||||
if (goods == null) {
|
||||
continue;
|
||||
}
|
||||
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
|
||||
|
||||
//商品参数索引
|
||||
if (goods.getParams() != null && !goods.getParams().isEmpty()) {
|
||||
List<GoodsParamsDTO> goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class);
|
||||
index = new EsGoodsIndex(goodsSku, goodsParamDTOS);
|
||||
LambdaQueryWrapper<Goods> goodsQueryWrapper = new LambdaQueryWrapper<>();
|
||||
goodsQueryWrapper.eq(Goods::getIsAuth, GoodsAuthEnum.PASS.name());
|
||||
goodsQueryWrapper.eq(Goods::getMarketEnable, GoodsStatusEnum.UPPER.name());
|
||||
|
||||
for (Goods goods : goodsService.list(goodsQueryWrapper)) {
|
||||
LambdaQueryWrapper<GoodsSku> skuQueryWrapper = new LambdaQueryWrapper<>();
|
||||
skuQueryWrapper.eq(GoodsSku::getGoodsId, goods.getId());
|
||||
skuQueryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name());
|
||||
skuQueryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
|
||||
|
||||
List<GoodsSku> goodsSkuList = goodsSkuService.list(skuQueryWrapper);
|
||||
int skuSource = 100;
|
||||
for (GoodsSku goodsSku : goodsSkuList) {
|
||||
EsGoodsIndex esGoodsIndex = wrapperEsGoodsIndex(goodsSku, goods);
|
||||
esGoodsIndex.setSkuSource(skuSource--);
|
||||
esGoodsIndices.add(esGoodsIndex);
|
||||
//库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量
|
||||
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
|
||||
}
|
||||
//商品分类索引
|
||||
if (goods.getCategoryPath() != null) {
|
||||
List<Category> categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(",")));
|
||||
if (!categories.isEmpty()) {
|
||||
index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ","));
|
||||
}
|
||||
}
|
||||
//商品品牌索引
|
||||
Brand brand = brandService.getById(goods.getBrandId());
|
||||
if (brand != null) {
|
||||
index.setBrandName(brand.getName());
|
||||
index.setBrandUrl(brand.getLogo());
|
||||
}
|
||||
//店铺分类索引
|
||||
if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) {
|
||||
List<StoreGoodsLabel> storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(",")));
|
||||
if (!storeGoodsLabels.isEmpty()) {
|
||||
index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ","));
|
||||
}
|
||||
}
|
||||
//促销索引
|
||||
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
|
||||
index.setPromotionMap(goodsCurrentPromotionMap);
|
||||
esGoodsIndices.add(index);
|
||||
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
|
||||
|
||||
}
|
||||
|
||||
//初始化商品索引
|
||||
this.initIndex(esGoodsIndices);
|
||||
} catch (Exception e) {
|
||||
@ -663,6 +645,40 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
|
||||
return elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME;
|
||||
}
|
||||
|
||||
private EsGoodsIndex wrapperEsGoodsIndex(GoodsSku goodsSku, Goods goods) {
|
||||
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
|
||||
|
||||
//商品参数索引
|
||||
if (goods.getParams() != null && !goods.getParams().isEmpty()) {
|
||||
List<GoodsParamsDTO> goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class);
|
||||
index = new EsGoodsIndex(goodsSku, goodsParamDTOS);
|
||||
}
|
||||
//商品分类索引
|
||||
if (goods.getCategoryPath() != null) {
|
||||
List<Category> categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(",")));
|
||||
if (!categories.isEmpty()) {
|
||||
index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ","));
|
||||
}
|
||||
}
|
||||
//商品品牌索引
|
||||
Brand brand = brandService.getById(goods.getBrandId());
|
||||
if (brand != null) {
|
||||
index.setBrandName(brand.getName());
|
||||
index.setBrandUrl(brand.getLogo());
|
||||
}
|
||||
//店铺分类索引
|
||||
if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) {
|
||||
List<StoreGoodsLabel> storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(",")));
|
||||
if (!storeGoodsLabels.isEmpty()) {
|
||||
index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ","));
|
||||
}
|
||||
}
|
||||
//促销索引
|
||||
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
|
||||
index.setPromotionMap(goodsCurrentPromotionMap);
|
||||
return index;
|
||||
}
|
||||
|
||||
private ActionListener<BulkByScrollResponse> actionListener() {
|
||||
return new ActionListener<BulkByScrollResponse>() {
|
||||
@Override
|
||||
|
@ -17,11 +17,15 @@ import cn.lili.modules.search.entity.dto.SelectorOptions;
|
||||
import cn.lili.modules.search.service.EsGoodsSearchService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
|
||||
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchQueryBuilder;
|
||||
import org.elasticsearch.index.query.Operator;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.query.functionscore.FieldValueFactorFunctionBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.GaussDecayFunctionBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
|
||||
import org.elasticsearch.search.aggregations.*;
|
||||
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
|
||||
@ -38,7 +42,7 @@ 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;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
@ -58,6 +62,8 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
private static final String ATTR_NAME = "attrList.name";
|
||||
private static final String ATTR_SORT = "attrList.sort";
|
||||
private static final String ATTR_BRAND_ID = "brandId";
|
||||
private static final String ATTR_BRAND_NAME = "brandNameAgg";
|
||||
private static final String ATTR_BRAND_URL = "brandUrlAgg";
|
||||
private static final String ATTR_NAME_KEY = "nameList";
|
||||
private static final String ATTR_VALUE_KEY = "valueList";
|
||||
/**
|
||||
@ -69,14 +75,14 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
* 缓存
|
||||
*/
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
private Cache<Object> cache;
|
||||
|
||||
@Override
|
||||
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);
|
||||
NativeSearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder(searchDTO, pageVo);
|
||||
NativeSearchQuery searchQuery = searchQueryBuilder.build();
|
||||
log.info("searchGoods DSL:{}", searchQuery.getQuery());
|
||||
SearchHits<EsGoodsIndex> search = restTemplate.search(searchQuery, EsGoodsIndex.class);
|
||||
@ -91,11 +97,11 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
List<String> hotWords = new ArrayList<>();
|
||||
// redis 排序中,下标从0开始,所以这里需要 -1 处理
|
||||
count = count - 1;
|
||||
Set<DefaultTypedTuple<Object>> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count);
|
||||
Set<ZSetOperations.TypedTuple<Object>> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count);
|
||||
if (set == null || set.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
for (DefaultTypedTuple<Object> defaultTypedTuple : set) {
|
||||
for (ZSetOperations.TypedTuple<Object> defaultTypedTuple : set) {
|
||||
hotWords.add(Objects.requireNonNull(defaultTypedTuple.getValue()).toString());
|
||||
}
|
||||
return hotWords;
|
||||
@ -108,15 +114,15 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
|
||||
@Override
|
||||
public EsGoodsRelatedInfo getSelector(EsGoodsSearchDTO goodsSearch, PageVO pageVo) {
|
||||
NativeSearchQueryBuilder builder = createSearchQueryBuilder(goodsSearch, null, true);
|
||||
NativeSearchQueryBuilder builder = createSearchQueryBuilder(goodsSearch, null);
|
||||
//分类
|
||||
AggregationBuilder categoryNameBuilder = AggregationBuilders.terms("categoryNameAgg").field("categoryNamePath.keyword");
|
||||
builder.addAggregation(AggregationBuilders.terms("categoryAgg").field("categoryPath").subAggregation(categoryNameBuilder));
|
||||
|
||||
//品牌
|
||||
AggregationBuilder brandNameBuilder = AggregationBuilders.terms("brandNameAgg").field("brandName.keyword");
|
||||
AggregationBuilder brandNameBuilder = AggregationBuilders.terms(ATTR_BRAND_NAME).field("brandName.keyword");
|
||||
builder.addAggregation(AggregationBuilders.terms("brandIdNameAgg").field(ATTR_BRAND_ID).size(Integer.MAX_VALUE).subAggregation(brandNameBuilder));
|
||||
AggregationBuilder brandUrlBuilder = AggregationBuilders.terms("brandUrlAgg").field("brandUrl.keyword");
|
||||
AggregationBuilder brandUrlBuilder = AggregationBuilders.terms(ATTR_BRAND_URL).field("brandUrl.keyword");
|
||||
builder.addAggregation(AggregationBuilders.terms("brandIdUrlAgg").field(ATTR_BRAND_ID).size(Integer.MAX_VALUE).subAggregation(brandUrlBuilder));
|
||||
//参数
|
||||
AggregationBuilder valuesBuilder = AggregationBuilders.terms("valueAgg").field(ATTR_VALUE);
|
||||
@ -152,29 +158,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
ParsedStringTerms categoryTerms = (ParsedStringTerms) aggregationMap.get("categoryAgg");
|
||||
List<? extends Terms.Bucket> categoryBuckets = categoryTerms.getBuckets();
|
||||
if (categoryBuckets != null && !categoryBuckets.isEmpty()) {
|
||||
for (Terms.Bucket categoryBucket : categoryBuckets) {
|
||||
String categoryPath = categoryBucket.getKey().toString();
|
||||
ParsedStringTerms categoryNameAgg = categoryBucket.getAggregations().get("categoryNameAgg");
|
||||
List<? extends Terms.Bucket> categoryNameBuckets = categoryNameAgg.getBuckets();
|
||||
|
||||
|
||||
String categoryNamePath = categoryPath;
|
||||
if (!categoryNameBuckets.isEmpty()) {
|
||||
categoryNamePath = categoryNameBuckets.get(0).getKey().toString();
|
||||
}
|
||||
String[] split = ArrayUtil.distinct(categoryPath.split(","));
|
||||
String[] nameSplit = categoryNamePath.split(",");
|
||||
if (split.length == nameSplit.length) {
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
SelectorOptions so = new SelectorOptions();
|
||||
so.setName(nameSplit[i]);
|
||||
so.setValue(split[i]);
|
||||
if (!categoryOptions.contains(so)) {
|
||||
categoryOptions.add(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
categoryOptions = this.convertCategoryOptions(categoryBuckets);
|
||||
}
|
||||
esGoodsRelatedInfo.setCategories(categoryOptions);
|
||||
|
||||
@ -185,46 +169,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
List<? extends Terms.Bucket> brandUrlBuckets = brandUrlTerms.getBuckets();
|
||||
List<SelectorOptions> brandOptions = new ArrayList<>();
|
||||
if (brandBuckets != null && !brandBuckets.isEmpty()) {
|
||||
for (int i = 0; i < brandBuckets.size(); i++) {
|
||||
String brandId = brandBuckets.get(i).getKey().toString();
|
||||
//当商品品牌id为0时,代表商品没有选择品牌,所以过滤掉品牌选择器
|
||||
if (brandId.equals("0")) {
|
||||
continue;
|
||||
}
|
||||
if (CharSequenceUtil.isNotEmpty(goodsSearch.getBrandId())) {
|
||||
List<String> brandList = Arrays.asList(goodsSearch.getBrandId().split("@"));
|
||||
if (brandList.contains(brandId)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String brandName = "";
|
||||
if (brandBuckets.get(i).getAggregations() != null && brandBuckets.get(i).getAggregations().get("brandNameAgg") != null) {
|
||||
ParsedStringTerms brandNameAgg = brandBuckets.get(i).getAggregations().get("brandNameAgg");
|
||||
List<? extends Terms.Bucket> categoryNameBuckets = brandNameAgg.getBuckets();
|
||||
if (categoryNameBuckets != null && !categoryNameBuckets.isEmpty()) {
|
||||
brandName = categoryNameBuckets.get(0).getKey().toString();
|
||||
}
|
||||
}
|
||||
|
||||
String brandUrl = "";
|
||||
if (brandUrlBuckets != null && !brandUrlBuckets.isEmpty() &&
|
||||
brandUrlBuckets.get(i).getAggregations() != null &&
|
||||
brandUrlBuckets.get(i).getAggregations().get("brandUrlAgg") != null) {
|
||||
|
||||
ParsedStringTerms brandUrlAgg = brandUrlBuckets.get(i).getAggregations().get("brandUrlAgg");
|
||||
List<? extends Terms.Bucket> categoryUrlBuckets = brandUrlAgg.getBuckets();
|
||||
if (categoryUrlBuckets != null && !categoryUrlBuckets.isEmpty()) {
|
||||
brandUrl = categoryUrlBuckets.get(0).getKey().toString();
|
||||
}
|
||||
|
||||
}
|
||||
SelectorOptions so = new SelectorOptions();
|
||||
so.setName(brandName);
|
||||
so.setValue(brandId);
|
||||
so.setUrl(brandUrl);
|
||||
brandOptions.add(so);
|
||||
}
|
||||
brandOptions = this.convertBrandOptions(goodsSearch, brandBuckets, brandUrlBuckets);
|
||||
}
|
||||
esGoodsRelatedInfo.setBrands(brandOptions);
|
||||
|
||||
@ -232,72 +177,167 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
ParsedNested attrTerms = (ParsedNested) aggregationMap.get("attrAgg");
|
||||
if (!goodsSearch.getNotShowCol().isEmpty()) {
|
||||
if (goodsSearch.getNotShowCol().containsKey(ATTR_NAME_KEY) && goodsSearch.getNotShowCol().containsKey(ATTR_VALUE_KEY)) {
|
||||
esGoodsRelatedInfo.setParamOptions(buildGoodsParam(attrTerms, goodsSearch.getNotShowCol().get(ATTR_NAME_KEY), goodsSearch.getNotShowCol().get(ATTR_VALUE_KEY)));
|
||||
esGoodsRelatedInfo.setParamOptions(buildGoodsParam(attrTerms, goodsSearch.getNotShowCol().get(ATTR_NAME_KEY)));
|
||||
}
|
||||
} else {
|
||||
esGoodsRelatedInfo.setParamOptions(buildGoodsParam(attrTerms, null, null));
|
||||
esGoodsRelatedInfo.setParamOptions(buildGoodsParam(attrTerms, null));
|
||||
}
|
||||
|
||||
return esGoodsRelatedInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将品牌聚合结果转换品牌选择项
|
||||
*
|
||||
* @param goodsSearch 查询参数
|
||||
* @param brandBuckets 品牌聚合结果桶
|
||||
* @param brandUrlBuckets 品牌地址聚合结果桶
|
||||
* @return 品牌选择项列表
|
||||
*/
|
||||
private List<SelectorOptions> convertBrandOptions(EsGoodsSearchDTO goodsSearch, List<? extends Terms.Bucket> brandBuckets, List<? extends Terms.Bucket> brandUrlBuckets) {
|
||||
List<SelectorOptions> brandOptions = new ArrayList<>();
|
||||
for (int i = 0; i < brandBuckets.size(); i++) {
|
||||
String brandId = brandBuckets.get(i).getKey().toString();
|
||||
//当商品品牌id为0时,代表商品没有选择品牌,所以过滤掉品牌选择器
|
||||
if (brandId.equals("0") ||
|
||||
(CharSequenceUtil.isNotEmpty(goodsSearch.getBrandId())
|
||||
&& Arrays.asList(goodsSearch.getBrandId().split("@")).contains(brandId))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String brandName = "";
|
||||
if (brandBuckets.get(i).getAggregations() != null && brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME) != null) {
|
||||
brandName = this.getAggregationsBrandOptions(brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME));
|
||||
}
|
||||
|
||||
String brandUrl = "";
|
||||
if (brandUrlBuckets != null && !brandUrlBuckets.isEmpty() &&
|
||||
brandUrlBuckets.get(i).getAggregations() != null &&
|
||||
brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL) != null) {
|
||||
brandUrl = this.getAggregationsBrandOptions(brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL));
|
||||
}
|
||||
SelectorOptions so = new SelectorOptions();
|
||||
so.setName(brandName);
|
||||
so.setValue(brandId);
|
||||
so.setUrl(brandUrl);
|
||||
brandOptions.add(so);
|
||||
}
|
||||
return brandOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取品牌聚合结果内的参数
|
||||
*
|
||||
* @param brandAgg 品牌聚合结果
|
||||
* @return 品牌聚合结果内的参数
|
||||
*/
|
||||
private String getAggregationsBrandOptions(ParsedStringTerms brandAgg) {
|
||||
List<? extends Terms.Bucket> brandAggBuckets = brandAgg.getBuckets();
|
||||
if (brandAggBuckets != null && !brandAggBuckets.isEmpty()) {
|
||||
return brandAggBuckets.get(0).getKey().toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将分类聚合结果转换分类选择项
|
||||
*
|
||||
* @param categoryBuckets 分类聚合结果
|
||||
* @return 分类选择项集合
|
||||
*/
|
||||
private List<SelectorOptions> convertCategoryOptions(List<? extends Terms.Bucket> categoryBuckets) {
|
||||
List<SelectorOptions> categoryOptions = new ArrayList<>();
|
||||
for (Terms.Bucket categoryBucket : categoryBuckets) {
|
||||
String categoryPath = categoryBucket.getKey().toString();
|
||||
ParsedStringTerms categoryNameAgg = categoryBucket.getAggregations().get("categoryNameAgg");
|
||||
List<? extends Terms.Bucket> categoryNameBuckets = categoryNameAgg.getBuckets();
|
||||
|
||||
|
||||
String categoryNamePath = categoryPath;
|
||||
if (!categoryNameBuckets.isEmpty()) {
|
||||
categoryNamePath = categoryNameBuckets.get(0).getKey().toString();
|
||||
}
|
||||
String[] split = ArrayUtil.distinct(categoryPath.split(","));
|
||||
String[] nameSplit = categoryNamePath.split(",");
|
||||
if (split.length == nameSplit.length) {
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
SelectorOptions so = new SelectorOptions();
|
||||
so.setName(nameSplit[i]);
|
||||
so.setValue(split[i]);
|
||||
if (!categoryOptions.contains(so)) {
|
||||
categoryOptions.add(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return categoryOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建商品参数信息
|
||||
*
|
||||
* @param attrTerms 商品参数搜索结果
|
||||
* @param nameList 查询的规格名
|
||||
* @param valueList 查询的规格项
|
||||
* @return 商品参数信息
|
||||
*/
|
||||
private List<ParamOptions> buildGoodsParam(ParsedNested attrTerms, List<String> nameList, List<String> valueList) {
|
||||
List<ParamOptions> paramOptions = new ArrayList<>();
|
||||
private List<ParamOptions> buildGoodsParam(ParsedNested attrTerms, List<String> nameList) {
|
||||
if (attrTerms != null) {
|
||||
Aggregations attrAggregations = attrTerms.getAggregations();
|
||||
Map<String, Aggregation> attrMap = attrAggregations.getAsMap();
|
||||
ParsedStringTerms nameAgg = (ParsedStringTerms) attrMap.get("nameAgg");
|
||||
|
||||
if (nameAgg != null) {
|
||||
List<? extends Terms.Bucket> nameBuckets = nameAgg.getBuckets();
|
||||
|
||||
for (Terms.Bucket bucket : nameBuckets) {
|
||||
String name = bucket.getKey().toString();
|
||||
ParamOptions paramOptions1 = new ParamOptions();
|
||||
ParsedStringTerms valueAgg = bucket.getAggregations().get("valueAgg");
|
||||
List<? extends Terms.Bucket> valueBuckets = valueAgg.getBuckets();
|
||||
List<String> valueSelectorList = new ArrayList<>();
|
||||
|
||||
for (Terms.Bucket valueBucket : valueBuckets) {
|
||||
String value = valueBucket.getKey().toString();
|
||||
|
||||
if (CharSequenceUtil.isNotEmpty(value)) {
|
||||
valueSelectorList.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
if (nameList == null || !nameList.contains(name)) {
|
||||
paramOptions1.setKey(name);
|
||||
paramOptions1.setValues(valueSelectorList);
|
||||
paramOptions.add(paramOptions1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return this.buildGoodsParamOptions(nameAgg, nameList);
|
||||
}
|
||||
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造商品参数属性
|
||||
*
|
||||
* @param nameAgg 商品参数聚合内容
|
||||
* @param nameList 查询的规格名
|
||||
* @return 商品参数属性集合
|
||||
*/
|
||||
private List<ParamOptions> buildGoodsParamOptions(ParsedStringTerms nameAgg, List<String> nameList) {
|
||||
List<ParamOptions> paramOptions = new ArrayList<>();
|
||||
List<? extends Terms.Bucket> nameBuckets = nameAgg.getBuckets();
|
||||
|
||||
for (Terms.Bucket bucket : nameBuckets) {
|
||||
String name = bucket.getKey().toString();
|
||||
ParamOptions paramOptions1 = new ParamOptions();
|
||||
ParsedStringTerms valueAgg = bucket.getAggregations().get("valueAgg");
|
||||
List<? extends Terms.Bucket> valueBuckets = valueAgg.getBuckets();
|
||||
List<String> valueSelectorList = new ArrayList<>();
|
||||
|
||||
for (Terms.Bucket valueBucket : valueBuckets) {
|
||||
String value = valueBucket.getKey().toString();
|
||||
|
||||
if (CharSequenceUtil.isNotEmpty(value)) {
|
||||
valueSelectorList.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
if (nameList == null || !nameList.contains(name)) {
|
||||
paramOptions1.setKey(name);
|
||||
paramOptions1.setValues(valueSelectorList);
|
||||
paramOptions.add(paramOptions1);
|
||||
}
|
||||
}
|
||||
return paramOptions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建es搜索builder
|
||||
*
|
||||
* @param searchDTO 搜索条件
|
||||
* @param pageVo 分页参数
|
||||
* @param isAggregation 是否是聚合查询
|
||||
* @param searchDTO 搜索条件
|
||||
* @param pageVo 分页参数
|
||||
* @return es搜索builder
|
||||
*/
|
||||
private NativeSearchQueryBuilder createSearchQueryBuilder(EsGoodsSearchDTO searchDTO, PageVO pageVo, boolean isAggregation) {
|
||||
private NativeSearchQueryBuilder createSearchQueryBuilder(EsGoodsSearchDTO searchDTO, PageVO pageVo) {
|
||||
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
|
||||
if (pageVo != null) {
|
||||
int pageNumber = pageVo.getPageNumber() - 1;
|
||||
@ -312,11 +352,9 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
if (searchDTO != null) {
|
||||
//过滤条件
|
||||
BoolQueryBuilder filterBuilder = QueryBuilders.boolQuery();
|
||||
//查询条件
|
||||
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
|
||||
|
||||
//对查询条件进行处理
|
||||
this.commonSearch(filterBuilder, queryBuilder, searchDTO, isAggregation);
|
||||
this.commonSearch(filterBuilder, searchDTO);
|
||||
|
||||
//未上架的商品不显示
|
||||
filterBuilder.must(QueryBuilders.matchQuery("marketEnable", GoodsStatusEnum.UPPER.name()));
|
||||
@ -328,16 +366,12 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
if (CharSequenceUtil.isEmpty(searchDTO.getKeyword())) {
|
||||
nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
|
||||
} else {
|
||||
this.keywordSearch(filterBuilder, queryBuilder, searchDTO.getKeyword(), isAggregation);
|
||||
this.keywordSearch(filterBuilder, searchDTO.getKeyword());
|
||||
}
|
||||
|
||||
//如果是聚合查询
|
||||
if (isAggregation) {
|
||||
nativeSearchQueryBuilder.withQuery(filterBuilder);
|
||||
} else {
|
||||
nativeSearchQueryBuilder.withQuery(queryBuilder);
|
||||
nativeSearchQueryBuilder.withFilter(filterBuilder);
|
||||
}
|
||||
|
||||
nativeSearchQueryBuilder.withQuery(filterBuilder);
|
||||
|
||||
|
||||
if (pageVo != null && CharSequenceUtil.isNotEmpty(pageVo.getOrder()) && CharSequenceUtil.isNotEmpty(pageVo.getSort())) {
|
||||
@ -354,11 +388,9 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
* 查询属性处理
|
||||
*
|
||||
* @param filterBuilder 过滤构造器
|
||||
* @param queryBuilder 查询构造器
|
||||
* @param searchDTO 查询参数
|
||||
* @param isAggregation 是否为聚合查询
|
||||
*/
|
||||
private void commonSearch(BoolQueryBuilder filterBuilder, BoolQueryBuilder queryBuilder, EsGoodsSearchDTO searchDTO, boolean isAggregation) {
|
||||
private void commonSearch(BoolQueryBuilder filterBuilder, EsGoodsSearchDTO searchDTO) {
|
||||
//品牌判定
|
||||
if (CharSequenceUtil.isNotEmpty(searchDTO.getBrandId())) {
|
||||
String[] brands = searchDTO.getBrandId().split("@");
|
||||
@ -385,46 +417,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
}
|
||||
//属性判定
|
||||
if (CharSequenceUtil.isNotEmpty(searchDTO.getProp())) {
|
||||
String[] props = searchDTO.getProp().split("@");
|
||||
List<String> nameList = new ArrayList<>();
|
||||
List<String> valueList = new ArrayList<>();
|
||||
Map<String, List<String>> valueMap = new HashMap<>(16);
|
||||
for (String prop : props) {
|
||||
String[] propValues = prop.split("_");
|
||||
String name = propValues[0];
|
||||
String value = propValues[1];
|
||||
if (!nameList.contains(name)) {
|
||||
nameList.add(name);
|
||||
}
|
||||
if (!valueList.contains(value)) {
|
||||
valueList.add(value);
|
||||
}
|
||||
//将同一规格名下的规格值分组
|
||||
if (!valueMap.containsKey(name)) {
|
||||
List<String> values = new ArrayList<>();
|
||||
values.add(value);
|
||||
valueMap.put(name, values);
|
||||
} else {
|
||||
valueMap.get(name).add(value);
|
||||
}
|
||||
}
|
||||
BoolQueryBuilder usedQueryBuilder;
|
||||
if (isAggregation) {
|
||||
usedQueryBuilder = filterBuilder;
|
||||
} else {
|
||||
usedQueryBuilder = queryBuilder;
|
||||
}
|
||||
//遍历所有的规格
|
||||
for (Map.Entry<String, List<String>> entry : valueMap.entrySet()) {
|
||||
usedQueryBuilder.must(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.wildcardQuery(ATTR_NAME, "*" + entry.getKey() + "*"), ScoreMode.None));
|
||||
BoolQueryBuilder shouldBuilder = QueryBuilders.boolQuery();
|
||||
for (String s : entry.getValue()) {
|
||||
shouldBuilder.should(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.wildcardQuery(ATTR_VALUE, "*" + s + "*"), ScoreMode.None));
|
||||
}
|
||||
usedQueryBuilder.must(shouldBuilder);
|
||||
}
|
||||
searchDTO.getNotShowCol().put(ATTR_NAME_KEY, nameList);
|
||||
searchDTO.getNotShowCol().put(ATTR_VALUE_KEY, valueList);
|
||||
this.propSearch(filterBuilder, searchDTO);
|
||||
}
|
||||
//价格区间判定
|
||||
if (CharSequenceUtil.isNotEmpty(searchDTO.getPrice())) {
|
||||
@ -442,47 +435,98 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品参数查询处理
|
||||
*
|
||||
* @param filterBuilder 过滤构造器
|
||||
* @param searchDTO 查询参数
|
||||
*/
|
||||
private void propSearch(BoolQueryBuilder filterBuilder, EsGoodsSearchDTO searchDTO) {
|
||||
String[] props = searchDTO.getProp().split("@");
|
||||
List<String> nameList = new ArrayList<>();
|
||||
List<String> valueList = new ArrayList<>();
|
||||
Map<String, List<String>> valueMap = new HashMap<>(16);
|
||||
for (String prop : props) {
|
||||
String[] propValues = prop.split("_");
|
||||
String name = propValues[0];
|
||||
String value = propValues[1];
|
||||
if (!nameList.contains(name)) {
|
||||
nameList.add(name);
|
||||
}
|
||||
if (!valueList.contains(value)) {
|
||||
valueList.add(value);
|
||||
}
|
||||
//将同一规格名下的规格值分组
|
||||
if (!valueMap.containsKey(name)) {
|
||||
List<String> values = new ArrayList<>();
|
||||
values.add(value);
|
||||
valueMap.put(name, values);
|
||||
} else {
|
||||
valueMap.get(name).add(value);
|
||||
}
|
||||
}
|
||||
//遍历所有的规格
|
||||
for (Map.Entry<String, List<String>> entry : valueMap.entrySet()) {
|
||||
filterBuilder.must(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.matchQuery(ATTR_NAME, entry.getKey()), ScoreMode.None));
|
||||
BoolQueryBuilder shouldBuilder = QueryBuilders.boolQuery();
|
||||
for (String s : entry.getValue()) {
|
||||
shouldBuilder.should(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.matchQuery(ATTR_VALUE, s), ScoreMode.None));
|
||||
}
|
||||
filterBuilder.must(shouldBuilder);
|
||||
}
|
||||
searchDTO.getNotShowCol().put(ATTR_NAME_KEY, nameList);
|
||||
searchDTO.getNotShowCol().put(ATTR_VALUE_KEY, valueList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关键字查询处理
|
||||
*
|
||||
* @param filterBuilder 过滤构造器
|
||||
* @param queryBuilder 查询构造器
|
||||
* @param keyword 关键字
|
||||
* @param isAggregation 是否为聚合查询
|
||||
*/
|
||||
private void keywordSearch(BoolQueryBuilder filterBuilder, BoolQueryBuilder queryBuilder, String keyword, boolean isAggregation) {
|
||||
private void keywordSearch(BoolQueryBuilder filterBuilder, String keyword) {
|
||||
List<FunctionScoreQueryBuilder.FilterFunctionBuilder> filterFunctionBuilders = new ArrayList<>();
|
||||
if (keyword.contains(" ")) {
|
||||
for (String s : keyword.split(" ")) {
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("goodsName", s).operator(Operator.AND),
|
||||
ScoreFunctionBuilders.weightFactorFunction(10)));
|
||||
//属性匹配
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.wildcardQuery(ATTR_VALUE, "*" + s + "*"), ScoreMode.None),
|
||||
ScoreFunctionBuilders.weightFactorFunction(8)));
|
||||
filterFunctionBuilders.addAll(this.buildKeywordSearch(s));
|
||||
}
|
||||
} else {
|
||||
//分词匹配
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("goodsName", keyword).operator(Operator.AND),
|
||||
ScoreFunctionBuilders.weightFactorFunction(10)));
|
||||
//属性匹配
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.wildcardQuery(ATTR_VALUE, "*" + keyword + "*"), ScoreMode.None),
|
||||
ScoreFunctionBuilders.weightFactorFunction(8)));
|
||||
filterFunctionBuilders = this.buildKeywordSearch(keyword);
|
||||
}
|
||||
|
||||
|
||||
FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()];
|
||||
filterFunctionBuilders.toArray(builders);
|
||||
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders)
|
||||
.scoreMode(FunctionScoreQuery.ScoreMode.SUM)
|
||||
.setMinScore(2);
|
||||
//聚合搜索则将结果放入过滤条件
|
||||
if (isAggregation) {
|
||||
filterBuilder.must(functionScoreQueryBuilder);
|
||||
}
|
||||
//否则放入查询条件
|
||||
else {
|
||||
queryBuilder.must(functionScoreQueryBuilder);
|
||||
}
|
||||
filterBuilder.must(functionScoreQueryBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造关键字查询
|
||||
*
|
||||
* @param keyword 关键字
|
||||
* @return 构造查询的集合
|
||||
*/
|
||||
private List<FunctionScoreQueryBuilder.FilterFunctionBuilder> buildKeywordSearch(String keyword) {
|
||||
List<FunctionScoreQueryBuilder.FilterFunctionBuilder> filterFunctionBuilders = new ArrayList<>();
|
||||
MatchQueryBuilder goodsNameQuery = QueryBuilders.matchQuery("goodsName", keyword).operator(Operator.AND);
|
||||
//分词匹配
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(goodsNameQuery,
|
||||
ScoreFunctionBuilders.weightFactorFunction(10)));
|
||||
//属性匹配
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.wildcardQuery(ATTR_VALUE, "*" + keyword + "*"), ScoreMode.None),
|
||||
ScoreFunctionBuilders.weightFactorFunction(8)));
|
||||
|
||||
GaussDecayFunctionBuilder skuNoScore = ScoreFunctionBuilders.gaussDecayFunction("skuSource", 100, 10).setWeight(7);
|
||||
FunctionScoreQueryBuilder.FilterFunctionBuilder skuNoBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(goodsNameQuery, skuNoScore);
|
||||
filterFunctionBuilders.add(skuNoBuilder);
|
||||
|
||||
FieldValueFactorFunctionBuilder buyCountScore = ScoreFunctionBuilders.fieldValueFactorFunction("buyCount").modifier(FieldValueFactorFunction.Modifier.LOG1P).setWeight(6);
|
||||
FunctionScoreQueryBuilder.FilterFunctionBuilder buyCountBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(goodsNameQuery, buyCountScore);
|
||||
filterFunctionBuilders.add(buyCountBuilder);
|
||||
return filterFunctionBuilders;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user