@Verify
@Override
public ResponseVo<List<GoodsSpuPageEsVo>> pageEs(EsPageParamPo pageParam, int page, int size) {
if (page < 1) {
throw new OSPException(OSPError.PARAM_ERROR, "page必须大于1");
}
if (size < 1 || size > 500) {
throw new OSPException(OSPError.PARAM_ERROR, "size范围1~100");
}
//Integer cusOrgId1 = sysConfigService.getName("SET_DEFAULT_USER_ENTERPRISE_INFO", Integer.class);
Pageable pageable = Pageable.newInstance(page, size, pageParam);
CustomerEnterprise customerEnterprise = null;
String cusEsPathPrefix = null;
if (null != pageParam.getCusOrgId()) {
customerEnterprise = customerEnterpriseMapper.selectById(pageParam.getCusOrgId());
if (customerEnterprise == null) {
log.error("商品使用客群属性es搜索,客群id不存在 {}", pageParam.getCusOrgId());
return ResponseVo.empty(pageable);
}
cusEsPathPrefix = "cusInfo." + customerEnterprise.getId() + ".";
}
List<String> cusEsPathPrefixs = new ArrayList<>();
if (CollectionUtils.isNotEmpty(pageParam.getCusOrgIds())) {
List<CustomerEnterprise> customerEnterprises = customerEnterpriseMapper.selectList(MCustomerEnterprise.in(MCustomerEnterprise.id, pageParam.getCusOrgIds()));
if (CollectionUtils.isEmpty(customerEnterprises)) {
log.error("商品使用客群属性es搜索,客群id不存在 {}", pageParam.getCusOrgId());
return ResponseVo.empty(pageable);
}
customerEnterprises.forEach(enterprise -> {
cusEsPathPrefixs.add("cusInfo." + enterprise.getId() + ".");
});
}
String indexName = sysConfigService.getName(Constants.ES_GOODS_TO_ELASTICSEARCH_INDEX_KEY, String.class, Constants.ES_GOODS_TO_ELASTICSEARCH_INDEX_DEFUALT_VALUE);
String minimumShouldMatch = sysConfigService.getName(Constants.ES_MINIMUM_SHOULD_MATCH_KEY, String.class, Constants.ES_MINIMUM_SHOULD_MATCH_DEFUALT_VALUE);
HighlightBuilder highlightBuilder = new HighlightBuilder();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if (StringUtils.isNotBlank(pageParam.getGoodsName())) {
boolQuery.must(QueryBuilders.multiMatchQuery(pageParam.getGoodsName(), "author", "masterName", "publishYear", "searchTags", "name", "typeName", "publishingHouse")
.field("name", 2.0f).operator(Operator.OR).minimumShouldMatch(minimumShouldMatch));
// 配置高亮显示
highlightBuilder.field("name");
highlightBuilder.field("author");
// 设置高亮标签
highlightBuilder.preTags("<span style=\"color:#FF0000;\">");
highlightBuilder.postTags("</span>");
/** 相似度搜索,提高全文搜索的_score评分 */
boolQuery.should(QueryBuilders.matchPhraseQuery("name", pageParam.getGoodsName()).slop(6));
boolQuery.should(QueryBuilders.matchPhraseQuery("isbn", pageParam.getGoodsName()).slop(4));
boolQuery.should(QueryBuilders.matchPhraseQuery("author", pageParam.getGoodsName()).slop(2));
boolQuery.should(QueryBuilders.matchPhraseQuery("searchTags", pageParam.getGoodsName()).slop(2));
boolQuery.should(QueryBuilders.matchPhraseQuery("typeName", pageParam.getGoodsName()).slop(2));
boolQuery.should(QueryBuilders.matchPhraseQuery("masterName", pageParam.getGoodsName()).slop(3));
boolQuery.should(QueryBuilders.matchPhraseQuery("publishYear", pageParam.getGoodsName()).slop(3));
boolQuery.should(QueryBuilders.matchPhraseQuery("publishingHouse", pageParam.getGoodsName()).slop(3));
// 设置minimum_should_match参数
boolQuery.minimumShouldMatch(1);
}
if (StringUtils.isNotBlank(pageParam.getSearchInfo())) {
boolQuery.must(QueryBuilders.multiMatchQuery(pageParam.getSearchInfo(), "name", "isbn", "spuId")
//TODO 这里重设了 字段的得分权重
.field("name", (float) 2.0).operator(Operator.OR).minimumShouldMatch(minimumShouldMatch));
highlightBuilder.field("name");
/**相似度搜索,提高全文搜索的_score的评分*/
boolQuery.should(QueryBuilders.matchPhraseQuery("name", pageParam.getSearchInfo()).slop(6));
boolQuery.should(QueryBuilders.matchPhraseQuery("isbn", pageParam.getSearchInfo()).slop(2));
boolQuery.should(QueryBuilders.matchPhraseQuery("spuId", pageParam.getSearchInfo()).slop(2));
}
if (StringUtils.isNotBlank(pageParam.getLeftName())) {
// 配置高亮显示
highlightBuilder.field("name");
// 设置高亮标签
highlightBuilder.preTags("<span style=\"color:#FF0000;\">");
highlightBuilder.postTags("</span>");
boolQuery.must(QueryBuilders.matchQuery("name", pageParam.getLeftName()));
// 可选:添加模糊匹配提高召回率
//boolQuery.should(QueryBuilders.matchQuery("name", pageParam.getLeftName()));
// 设置minimum_should_match
//boolQuery.minimumShouldMatch(0);
}
String productClassCode = pageParam.getProductClassCode();
if (customerEnterprise != null) {
boolQuery.must(QueryBuilders.termQuery(cusEsPathPrefix + "canGoods", "true"));
boolQuery.must(QueryBuilders.termQuery(cusEsPathPrefix + "canSupplierCode", "true"));
if (!productClassCode.equals(ProductClassCodeEnum.VIRTUAL.code)) {
boolQuery.must(QueryBuilders.termQuery(cusEsPathPrefix + "canType", "true"));
}
}
if (CollectionUtils.isNotEmpty(cusEsPathPrefixs)) {
BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();
cusEsPathPrefixs.forEach(prefix -> {
// 为每个前缀创建一个必须满足所有条件的布尔查询
BoolQueryBuilder prefixQuery = QueryBuilders.boolQuery();
prefixQuery.must(QueryBuilders.termQuery(prefix + "canGoods", "true"));
prefixQuery.must(QueryBuilders.termQuery(prefix + "canSupplierCode", "true"));
if (!productClassCode.equals(ProductClassCodeEnum.VIRTUAL.code)) {
prefixQuery.must(QueryBuilders.termQuery(prefix + "canType", "true"));
}
// 将每个前缀的查询添加到主查询中作为 should 条件
subBoolQuery.should(prefixQuery);
});
// 设置 minimum_should_match 为 1,表示只需满足任意一个前缀的所有条件即可
subBoolQuery.minimumShouldMatch(1);
boolQuery.must(subBoolQuery);
}
if (null != pageParam.getLowPrice() || null != pageParam.getHighPrice()) {
RangeQueryBuilder rangeQueryBuilder = null;
if (customerEnterprise != null) {
rangeQueryBuilder = QueryBuilders.rangeQuery(cusEsPathPrefix + "price");
} else {
rangeQueryBuilder = QueryBuilders.rangeQuery("sellPrice");
}
if (null != pageParam.getLowPrice()) {
rangeQueryBuilder.gte(pageParam.getLowPrice());
}
if (null != pageParam.getHighPrice()) {
rangeQueryBuilder.lte(pageParam.getHighPrice());
}
boolQuery.must(rangeQueryBuilder);
}
if (null != pageParam.getCreateTimeStart() || null != pageParam.getCreateTimeEnd()) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("createTimeMillis");
if (null != pageParam.getCreateTimeStart()) {
rangeQueryBuilder.gte(pageParam.getCreateTimeStart());
}
if (null != pageParam.getCreateTimeEnd()) {
rangeQueryBuilder.lte(pageParam.getCreateTimeEnd());
}
boolQuery.must(rangeQueryBuilder);
}
if (null != pageParam.getUpdateTimeStart() || null != pageParam.getUpdateTimeEnd()) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("updateTimeMillis");
if (null != pageParam.getUpdateTimeStart()) {
rangeQueryBuilder.gte(pageParam.getUpdateTimeStart());
}
if (null != pageParam.getUpdateTimeEnd()) {
rangeQueryBuilder.lte(pageParam.getUpdateTimeEnd());
}
boolQuery.must(rangeQueryBuilder);
}
if (null != pageParam.getUpTimeStart() || null != pageParam.getUpTimeEnd()) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("upTimeMillis");
if (null != pageParam.getUpTimeStart()) {
rangeQueryBuilder.gte(pageParam.getUpTimeStart());
}
if (null != pageParam.getUpTimeEnd()) {
rangeQueryBuilder.lte(pageParam.getUpTimeEnd());
}
boolQuery.must(rangeQueryBuilder);
}
if (null != pageParam.getStockStart() || null != pageParam.getStockEnd()) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("stock");
if (null != pageParam.getStockStart()) {
rangeQueryBuilder.gte(pageParam.getStockStart());
}
if (null != pageParam.getStockEnd()) {
rangeQueryBuilder.lte(pageParam.getStockEnd());
}
boolQuery.must(rangeQueryBuilder);
}
if (null != pageParam.getOnTop()) {
boolQuery.must(QueryBuilders.termQuery("onTop", pageParam.getOnTop()));
}
if (null != pageParam.getSupplierCodeList() && !pageParam.getSupplierCodeList().isEmpty()) {
BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();
pageParam.getSupplierCodeList().forEach(one -> {
subBoolQuery.should(QueryBuilders.termQuery("supplierCode", one));
});
boolQuery.must(subBoolQuery);
}
if (null != pageParam.getProductClassCodeList() && !pageParam.getProductClassCodeList().isEmpty()) {
BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();
pageParam.getProductClassCodeList().forEach(one -> {
subBoolQuery.should(QueryBuilders.termQuery("productClassCode.keyword", one));
});
boolQuery.must(subBoolQuery);
}
if (StringUtils.isNotBlank(pageParam.getProductClassCode())) {
boolQuery.must(QueryBuilders.termQuery("productClassCode.keyword", pageParam.getProductClassCode()));
// boolQuery.must(QueryBuilders.termQuery("label.count", pageParam.getProductClassCode()));
}/* else {
boolQuery.must(QueryBuilders.termQuery("productClassCode.keyword", ProductClassCodeEnum.BOOK.code));
}*/
if (null != pageParam.getGoodsTypeIdList() && !pageParam.getGoodsTypeIdList().isEmpty()) {
MGoodsType.in(MGoodsType.code, pageParam.getGoodsTypeIdList()).eq(MGoodsType.onDel, DeleteEnum.NO_DELETE.code).eq(MGoodsType.channelId, "3106").eq(MGoodsType.status, YESOrNOEnum.STATUS_1.code);
if (StringUtils.isNotBlank(pageParam.getProductClassCode())) {
MGoodsType.eq(MGoodsType.productClassCode, pageParam.getProductClassCode());
} else {
MGoodsType.eq(MGoodsType.productClassCode, ProductClassCodeEnum.BOOK.code);
}
List<GoodsType> typeList = goodsTypeMapper.selectList(MGoodsType.build());
Stream<String> typePathList = typeList.stream().map(GoodsType::getPath);
BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();
typePathList.forEach(one -> {
subBoolQuery.should(QueryBuilders.prefixQuery("typePath", one));
});
boolQuery.must(subBoolQuery);
}
if (null != pageParam.getSpuIds() && !pageParam.getSpuIds().isEmpty()) {
BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();
pageParam.getSpuIds().forEach(one -> {
subBoolQuery.should(QueryBuilders.termQuery("spuId", one));
});
boolQuery.must(subBoolQuery);
}
if (CollectionUtils.isNotEmpty(pageParam.getBanSpuIds())) {
BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();
pageParam.getBanSpuIds().forEach(one -> {
subBoolQuery.should(QueryBuilders.termQuery("spuId", one));
});
boolQuery.mustNot(subBoolQuery);
}
if (null != pageParam.getTags() && !pageParam.getTags().isEmpty()) {
// boolQuery.must(QueryBuilders.matchQuery(channelKey + "tag", pageParam.getTags().stream().collect(Collectors.joining(" "))).minimumShouldMatch("60%"));
Map<String, Object> params = Maps.newHashMap();
String scriptStr = "";
for (int i = 0; i < pageParam.getTags().size(); i++) {
params.put("to_tag" + i, pageParam.getTags().get(i));
scriptStr += "doc['tags.keyword'].values.contains(params.to_tag" + i + ") ";
if (i != (pageParam.getTags().size() - 1)) {
scriptStr += "|| ";
}
}
Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG, scriptStr, params);
boolQuery.must(QueryBuilders.scriptQuery(script));
}
if (null != pageParam.getStatus()) {
boolQuery.must(QueryBuilders.termQuery("status", pageParam.getStatus()));
}
if (null != pageParam.getMasterStatus()) {
boolQuery.must(QueryBuilders.termQuery("masterStatus", pageParam.getMasterStatus()));
}
boolQuery.must(QueryBuilders.termQuery("onDel", DeleteEnum.NO_DELETE.code));
boolQuery.must(QueryBuilders.termQuery("masterOnDel", DeleteEnum.NO_DELETE.code));
searchSourceBuilder.query(boolQuery);
if (!highlightBuilder.fields().isEmpty()) {
searchSourceBuilder.highlighter(highlightBuilder);
}
searchSourceBuilder.from((page - 1) * size);
searchSourceBuilder.size(size);
//随机分页查询 放在排序前,否则无效
if (null != pageParam.getIsOpenRandomPage() && pageParam.getIsOpenRandomPage().equals(1)) {
Script script = new Script("Math.random()");
ScriptSortBuilder sortBuilder = new ScriptSortBuilder(script, ScriptSortBuilder.ScriptSortType.NUMBER);
searchSourceBuilder.sort(sortBuilder);
}
/**是否默认排序*/
boolean defaultSort = true;
if (null != pageParam.getFixedPriceSort()) {
defaultSort = false;
searchSourceBuilder.sort("fixedPrice", SortTypeEnum.TYPE_1.code.equals(pageParam.getFixedPriceSort()) ? SortOrder.ASC : SortOrder.DESC);
}
if (null != pageParam.getUpTimeSort()) {
defaultSort = false;
searchSourceBuilder.sort("upTimeMillis", SortTypeEnum.TYPE_1.code.equals(pageParam.getUpTimeSort()) ? SortOrder.ASC : SortOrder.DESC);
}
if (null != pageParam.getCreateSort()) {
defaultSort = false;
searchSourceBuilder.sort("createTimeMillis", SortTypeEnum.TYPE_1.code.equals(pageParam.getCreateSort()) ? SortOrder.ASC : SortOrder.DESC);
}
if (null != pageParam.getUpdateSort()) {
defaultSort = false;
searchSourceBuilder.sort("updateTimeMillis", SortTypeEnum.TYPE_1.code.equals(pageParam.getUpdateSort()) ? SortOrder.ASC : SortOrder.DESC);
}
if (null != pageParam.getRecommendSort()) {
defaultSort = false;
Map<String, Object> params = Maps.newHashMap();
params.put("to_tag", "推荐");
// Script script=new Script(Script.DEFAULT_SCRIPT_TYPE,Script.DEFAULT_SCRIPT_LANG,"doc['"+channelKey+"tag.keyword'].value==params.to_tag?1:0",params);
/**同时存在多个值时候,原来的== 判断就不起作用*/
Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG, "doc['tags.keyword'].values.contains(params.to_tag)?1:0", params);
ScriptSortBuilder scriptSortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortTypeEnum.TYPE_1.code.equals(pageParam.getRecommendSort()) ? SortOrder.ASC : SortOrder.DESC);
searchSourceBuilder.sort(scriptSortBuilder);
searchSourceBuilder.sort(SortBuilders.fieldSort("onTop").order(SortOrder.DESC).unmappedType("integer"));
searchSourceBuilder.sort(SortBuilders.fieldSort("sort").order(SortOrder.ASC).unmappedType("integer"));
}
if (null != pageParam.getPriceSort()) {
defaultSort = false;
if (customerEnterprise != null) {
searchSourceBuilder.sort(cusEsPathPrefix + "price", SortTypeEnum.TYPE_1.code.equals(pageParam.getPriceSort()) ? SortOrder.ASC : SortOrder.DESC);
} else {
searchSourceBuilder.sort("sellPrice", SortTypeEnum.TYPE_1.code.equals(pageParam.getPriceSort()) ? SortOrder.ASC : SortOrder.DESC);
}
}
if (null != pageParam.getSaleCntSort()) {
defaultSort = false;
searchSourceBuilder.sort("spuSaleCnt", SortTypeEnum.TYPE_1.code.equals(pageParam.getSaleCntSort()) ? SortOrder.ASC : SortOrder.DESC);
}
if (null != pageParam.getPublishTimeSort()) {
// 根据出版时间排序
defaultSort = false;
FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("publishTimeMillis").order(SortTypeEnum.TYPE_1.code.equals(pageParam.getPublishTimeSort()) ? SortOrder.ASC : SortOrder.DESC).unmappedType("number");
searchSourceBuilder.sort(fieldSortBuilder);
}
if (StringUtils.isNotBlank(pageParam.getLeftName())) {
searchSourceBuilder.sort("_score", SortOrder.DESC);
} else {
if (defaultSort) {
if (StringUtils.isNotBlank(pageParam.getGoodsName())) {
searchSourceBuilder.sort("_score", SortOrder.DESC);
}
/**当字段不存在的时候,排序需要指定 默认的字段数据类型 否则会报错*/
searchSourceBuilder.sort(SortBuilders.fieldSort("onTop").order(SortOrder.DESC).unmappedType("integer"));
searchSourceBuilder.sort(SortBuilders.fieldSort("sort").order(SortOrder.ASC).unmappedType("integer"));
}
}
log.info("搜索查询语句 index:{}:\n{}", indexName, searchSourceBuilder.toString());
Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex(indexName).addType(Constants.ES_TYPE_NAME).build();
try {
SearchResult jr = null;
jr = jestClient.execute(search);
if (log.isDebugEnabled()) {
log.debug("搜索查询返回:{}", jr == null ? "" : jr.getJsonString());
}
List<SearchResult.Hit<NEsGoodsSpuVo, Void>> hits = jr.getHits(NEsGoodsSpuVo.class);
log.info("搜索查询返回数据条数 ----> {}", hits.size());
List<GoodsSpuPageEsVo> goodsSpuPageEsVos = new ArrayList<>();
hits.forEach(hit -> {
GoodsSpuPageEsVo goodsSpuPageEsVo = BeanUtil.copyProperties(hit.source, GoodsSpuPageEsVo.class);
if (hit.highlight != null && !hit.highlight.isEmpty()) {
hit.highlight.entrySet().forEach(highlight -> {
if (highlight.getKey().equals("name") && !highlight.getValue().isEmpty()) {
goodsSpuPageEsVo.setHighlightName(highlight.getValue().get(0));
}
if (highlight.getKey().equals("author") && !highlight.getValue().isEmpty()) {
goodsSpuPageEsVo.setHighlightAuthor(highlight.getValue().get(0));
}
});
}
goodsSpuPageEsVos.add(goodsSpuPageEsVo);
});
pageable.setTotal(jr.getTotal());
return ResponseVo.sucess(goodsSpuPageEsVos, pageable);
} catch (IOException e) {
log.error("查询es异常", e);
throw new OSPException(OSPError.RUNTIME_ERROR, "商品搜索引擎异常");
}
}价格区间,营销分类类型编码,推荐标签,推荐关键词
最新发布