master:系统ES搜索优化;

pull/1121/head
liujiang 2025-11-23 23:29:53 +08:00
parent 266350f7da
commit 6a8db21a4c
3 changed files with 48 additions and 387 deletions

View File

@ -14,7 +14,10 @@ import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.es.EsClientWrapper;
import com.ruoyi.framework.notice.fs.FsNotice;
import com.ruoyi.xkt.domain.*;
import com.ruoyi.xkt.domain.Store;
import com.ruoyi.xkt.domain.StoreProduct;
import com.ruoyi.xkt.domain.StoreProductCategoryAttribute;
import com.ruoyi.xkt.domain.SysProductCategory;
import com.ruoyi.xkt.dto.es.ESProductDTO;
import com.ruoyi.xkt.dto.storeProdColorPrice.StoreProdMinPriceDTO;
import com.ruoyi.xkt.dto.storeProductFile.StoreProdMainPicDTO;
@ -193,99 +196,6 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
// 将搜索条件添加到主查询
boolQueryBuilder.must(searchBoolQuery.build()._toQuery());
}
/*// 优化搜索逻辑 - 修复版
if (StringUtils.isNotBlank(searchDTO.getSearch())) {
String searchTerm = searchDTO.getSearch().trim();
// 创建专门的搜索 bool query
BoolQuery.Builder searchBoolQuery = new BoolQuery.Builder();
// 方案1使用 MultiMatchQuery 进行智能分词搜索(主要方式)
MultiMatchQuery multiMatchQuery = MultiMatchQuery.of(m -> m
.query(searchTerm)
.fields("storeName^3", "prodTitle^2", "prodCateName", "parCateName", "prodArtNum^2")
.type(TextQueryType.BestFields) // 使用最佳字段匹配
);
searchBoolQuery.should(multiMatchQuery._toQuery());
// 方案2对每个字段单独使用 MatchQuery作为补充
String[] matchFields = {"storeName", "prodTitle", "prodCateName", "parCateName", "prodArtNum"};
for (String field : matchFields) {
MatchQuery matchQuery = MatchQuery.of(m -> m
.field(field)
.query(searchTerm)
.operator(Operator.Or) // 使用 OR 操作符,匹配任意分词
);
searchBoolQuery.should(matchQuery._toQuery());
}
// 方案3对于包含英文或数字的情况添加通配符查询到 keyword 字段
if (containsEnglishOrNumber(searchTerm)) {
String wildcardPattern = "*" + searchTerm + "*";
String[] keywordFields = {
"storeName.keyword", "prodTitle.keyword", "prodArtNum.keyword"
};
for (String field : keywordFields) {
WildcardQuery wildcardQuery = WildcardQuery.of(w -> w
.field(field)
.value(wildcardPattern)
.boost(0.3f) // 降低权重
);
searchBoolQuery.should(wildcardQuery._toQuery());
}
}
// 方案4拆分成单个字符进行通配符匹配针对混合字符串
if (searchTerm.length() > 1) {
// 对每个字符单独进行通配符匹配
for (int i = 0; i < searchTerm.length(); i++) {
char c = searchTerm.charAt(i);
if (Character.isLetterOrDigit(c)) {
String charPattern = "*" + c + "*";
WildcardQuery charQuery = WildcardQuery.of(w -> w
.field("storeName.keyword")
.value(charPattern)
.boost(0.1f) // 很低权重,确保不影响主要结果
);
searchBoolQuery.should(charQuery._toQuery());
}
}
}
// 设置最小匹配条件
searchBoolQuery.minimumShouldMatch("1");
// 将搜索条件添加到主查询
boolQueryBuilder.must(searchBoolQuery.build()._toQuery());
}*/
// 档口ID 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getStoreIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
@ -376,8 +286,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
}
// 处理混合文本搜索(中英文数字混合)
/**
*
* @param searchTerm
* @param searchBoolQuery
*/
private void handleMixedTextSearch(String searchTerm, BoolQuery.Builder searchBoolQuery) {
// 1. 整体多字段匹配(主要方式)
MultiMatchQuery multiMatchQuery = MultiMatchQuery.of(m -> m
@ -416,7 +329,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
}
}
// 处理短英文数字搜索
/**
*
* @param searchTerm
* @param searchBoolQuery
*/
private void handleShortEnglishNumberSearch(String searchTerm, BoolQuery.Builder searchBoolQuery) {
// 1. 前缀匹配(最高优先级)
String prefixPattern = searchTerm + "*";
@ -443,7 +360,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
searchBoolQuery.should(artNumQuery._toQuery());
}
// 处理短中文搜索
/**
*
* @param searchTerm
* @param searchBoolQuery
*/
private void handleShortChineseSearch(String searchTerm, BoolQuery.Builder searchBoolQuery) {
// 使用 MultiMatchQuery 进行分词匹配
MultiMatchQuery multiMatchQuery = MultiMatchQuery.of(m -> m
@ -454,7 +375,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
searchBoolQuery.should(multiMatchQuery._toQuery());
}
// 处理标准长文本搜索
/**
*
* @param searchTerm
* @param searchBoolQuery
*/
private void handleStandardTextSearch(String searchTerm, BoolQuery.Builder searchBoolQuery) {
// 使用标准的 MultiMatchQuery
MultiMatchQuery multiMatchQuery = MultiMatchQuery.of(m -> m
@ -466,7 +391,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
}
// 判断是否包含中文
/**
*
* @param str
* @return
*/
private boolean containsChinese(String str) {
if (str == null) return false;
for (int i = 0; i < str.length(); i++) {
@ -478,7 +407,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
return false;
}
// 判断是否包含英文或数字
/**
*
* @param str
* @return
*/
private boolean containsEnglishOrNumber(String str) {
if (str == null) return false;
for (int i = 0; i < str.length(); i++) {
@ -490,7 +423,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
return false;
}
// 提取英文数字部分
/**
*
* @param str
* @return
*/
private String extractEnglishNumberPart(String str) {
if (str == null) return "";
StringBuilder sb = new StringBuilder();
@ -503,7 +440,11 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
return sb.toString();
}
// 提取中文部分
/**
*
* @param str
* @return
*/
private String extractChinesePart(String str) {
if (str == null) return "";
StringBuilder sb = new StringBuilder();

View File

@ -4,10 +4,6 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@ -17,7 +13,6 @@ import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.AdType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.es.EsClientWrapper;
import com.ruoyi.xkt.domain.*;
@ -39,6 +34,7 @@ import com.ruoyi.xkt.dto.website.AppStrengthSearchDTO;
import com.ruoyi.xkt.dto.website.IndexSearchDTO;
import com.ruoyi.xkt.enums.*;
import com.ruoyi.xkt.mapper.*;
import com.ruoyi.xkt.service.IElasticSearchService;
import com.ruoyi.xkt.service.IWebsiteAPPService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
@ -51,8 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@ -79,6 +73,7 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService {
final UserSubscriptionsMapper userSubMapper;
final UserFavoritesMapper userFavMapper;
final StoreMemberMapper storeMemberMapper;
final IElasticSearchService esService;
@Value("${es.indexName}")
private String ES_INDEX_NAME;
@ -1035,105 +1030,7 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService {
@Override
@Transactional(readOnly = true)
public Page<ESProductDTO> search(IndexSearchDTO searchDTO) throws IOException {
// 构建 bool 查询
BoolQuery.Builder boolQuery = new BoolQuery.Builder();
// 添加 price 范围查询
if (ObjectUtils.isNotEmpty(searchDTO.getMinPrice()) && ObjectUtils.isNotEmpty(searchDTO.getMaxPrice())) {
RangeQuery.Builder builder = new RangeQuery.Builder();
builder.number(NumberRangeQuery.of(n -> n.field("prodPrice").gte(Double.valueOf(searchDTO.getMinPrice()))
.lte(Double.valueOf(searchDTO.getMaxPrice()))));
boolQuery.filter(builder.build()._toQuery());
}
// 添加 multiMatch 查询
if (StringUtils.isNotBlank(searchDTO.getSearch())) {
MultiMatchQuery multiMatchQuery = MultiMatchQuery.of(m -> m
.query(searchDTO.getSearch())
.fields("storeName", "prodTitle", "prodCateName", "parCateName", "prodArtNum")
);
boolQuery.must(multiMatchQuery._toQuery());
}
// 档口ID列表 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getStoreIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getStoreIdList().stream()
.map(WebsiteAPPServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQuery.filter(f -> f.terms(t -> t.field("storeId").terms(termsQueryField)));
}
// 添加prodStatus 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getProdStatusList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getProdStatusList().stream()
.map(WebsiteAPPServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQuery.filter(f -> f.terms(t -> t.field("prodStatus").terms(termsQueryField)));
}
// 添加 prodCateId 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getProdCateIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getProdCateIdList().stream()
.map(WebsiteAPPServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQuery.filter(f -> f.terms(t -> t.field("prodCateId").terms(termsQueryField)));
}
// 添加 parCateId 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getParCateIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getParCateIdList().stream()
.map(WebsiteAPPServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQuery.filter(f -> f.terms(t -> t.field("parCateId").terms(termsQueryField)));
}
// 添加 style 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getStyleList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getStyleList().stream()
.map(WebsiteAPPServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQuery.filter(f -> f.terms(t -> t.field("style.keyword").terms(termsQueryField)));
}
// 添加 season 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getSeasonList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getSeasonList().stream()
.map(WebsiteAPPServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQuery.filter(f -> f.terms(t -> t.field("season.keyword").terms(termsQueryField)));
}
// 如果是按照时间过滤,则表明是“新品”,则限制 时间范围 20天前到现在
if (Objects.equals(searchDTO.getSort(), "createTime")) {
// 当前时间
final String nowStr = DateUtils.getTime();
// 当前时间往前推20天获取当天的0点0分0秒
LocalDateTime ago = LocalDateTime.now().minusDays(20).withHour(0).withMinute(0).withSecond(0);
// ago 转化为 yyyy-MM-dd HH:mm:ss
String agoStr = ago.format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS));
RangeQuery.Builder builder = new RangeQuery.Builder();
builder.date(DateRangeQuery.of(d -> d.field("createTime").gte(agoStr).lte(nowStr)));
boolQuery.filter(builder.build()._toQuery());
}
// 构建最终的查询
Query query = new Query.Builder().bool(boolQuery.build()).build();
// 执行搜索
SearchResponse<ESProductDTO> resList = esClientWrapper.getEsClient()
.search(s -> s.index(ES_INDEX_NAME)
.query(query)
.from((searchDTO.getPageNum() - 1) * searchDTO.getPageSize())
.size(searchDTO.getPageSize())
.sort(Arrays.asList(
SortOptions.of(so -> so.field(f -> f.field(searchDTO.getSort()).order(searchDTO.getOrder()))),
SortOptions.of(so -> so.field(f -> f.field("storeWeight").order(SortOrder.Desc)))
)),
ESProductDTO.class);
final long total = resList.hits().total().value();
final List<ESProductDTO> esProdList = resList.hits().hits().stream().map(x -> x.source().setStoreProdId(x.id())).collect(Collectors.toList());
return new Page<>(searchDTO.getPageNum(), searchDTO.getPageSize(), total / searchDTO.getPageSize() + 1, total, esProdList);
return this.esService.search(searchDTO);
}
/**

View File

@ -3,11 +3,6 @@ package com.ruoyi.xkt.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.constant.CacheConstants;
@ -16,7 +11,6 @@ import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.AdType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.es.EsClientWrapper;
import com.ruoyi.xkt.domain.*;
@ -57,8 +51,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@ -824,11 +816,6 @@ public class WebsitePCServiceImpl implements IWebsitePCService {
return tempList.stream().limit(limitCount).collect(Collectors.toList());
}
private static FieldValue newFieldValue(String value) {
return FieldValue.of(value);
}
/**
*
*
@ -837,163 +824,7 @@ public class WebsitePCServiceImpl implements IWebsitePCService {
@Override
@Transactional(readOnly = true)
public Page<ESProductDTO> search(IndexSearchDTO searchDTO) throws IOException {
return this.esService.search(searchDTO);
/*
// 构建 bool 查询
BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();
// 添加 price 范围查询
if (ObjectUtils.isNotEmpty(searchDTO.getMinPrice()) && ObjectUtils.isNotEmpty(searchDTO.getMaxPrice())) {
RangeQuery.Builder rangeBuilder = new RangeQuery.Builder();
rangeBuilder.number(NumberRangeQuery.of(n -> n.field("prodPrice").gte(Double.valueOf(searchDTO.getMinPrice()))
.lte(Double.valueOf(searchDTO.getMaxPrice()))));
boolQueryBuilder.filter(rangeBuilder.build()._toQuery());
}
// 优化搜索逻辑
if (StringUtils.isNotBlank(searchDTO.getSearch())) {
String searchTerm = searchDTO.getSearch().trim();
// 创建专门的搜索 bool query
BoolQuery.Builder searchBoolQuery = new BoolQuery.Builder();
// 1. 使用 MatchQuery 利用 IK 分词器(主要搜索方式)
String[] matchFields = {"storeName", "prodTitle", "prodCateName", "parCateName", "prodArtNum"};
for (String field : matchFields) {
MatchQuery matchQuery = MatchQuery.of(m -> m
.field(field)
.query(searchTerm)
.boost(field.equals("storeName") || field.equals("prodArtNum") ? 2.0f : 1.0f)
);
searchBoolQuery.should(matchQuery._toQuery());
}
// 2. 对于短字符1-2个字符添加通配符查询到 keyword 字段
if (searchTerm.length() <= 2) {
String wildcardPattern = "*" + searchTerm + "*";
String[] keywordFields = {
"storeName.keyword", "prodTitle.keyword", "prodCateName.keyword",
"parCateName.keyword", "prodArtNum.keyword"
};
for (String field : keywordFields) {
WildcardQuery wildcardQuery = WildcardQuery.of(w -> w
.field(field)
.value(wildcardPattern)
.boost(0.5f) // 降低权重,优先使用分词匹配
);
searchBoolQuery.should(wildcardQuery._toQuery());
}
// 3. 额外添加前缀匹配,对短字符特别有效
String prefixPattern = searchTerm + "*";
WildcardQuery prefixQuery = WildcardQuery.of(w -> w
.field("storeName.keyword")
.value(prefixPattern)
.boost(1.0f)
);
searchBoolQuery.should(prefixQuery._toQuery());
}
// 4. 对于中文单字,添加专门的匹配
if (searchTerm.length() == 1 && isChineseCharacter(searchTerm)) {
// 使用 term 查询在 keyword 字段上精确匹配
String[] keywordFields = {
"storeName.keyword", "prodTitle.keyword", "prodCateName.keyword",
"parCateName.keyword", "prodArtNum.keyword"
};
for (String field : keywordFields) {
WildcardQuery charQuery = WildcardQuery.of(w -> w
.field(field)
.value("*" + searchTerm + "*")
.boost(0.8f)
);
searchBoolQuery.should(charQuery._toQuery());
}
}
// 设置最小匹配条件
searchBoolQuery.minimumShouldMatch("1");
// 将搜索条件添加到主查询
boolQueryBuilder.must(searchBoolQuery.build()._toQuery());
}
// 档口ID 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getStoreIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getStoreIdList().stream()
.map(WebsitePCServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("storeId").terms(termsQueryField)));
}
// 添加prodStatus 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getProdStatusList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getProdStatusList().stream()
.map(WebsitePCServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("prodStatus").terms(termsQueryField)));
}
// 添加 prodCateId 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getProdCateIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getProdCateIdList().stream()
.map(WebsitePCServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("prodCateId").terms(termsQueryField)));
}
// 添加 parCateId 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getParCateIdList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getParCateIdList().stream()
.map(WebsitePCServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("parCateId").terms(termsQueryField)));
}
// 添加 style 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getStyleList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getStyleList().stream()
.map(WebsitePCServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("style.keyword").terms(termsQueryField)));
}
// 添加 season 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getSeasonList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getSeasonList().stream()
.map(WebsitePCServiceImpl::newFieldValue)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("season.keyword").terms(termsQueryField)));
}
// 如果是按照时间过滤,则表明是"新品",则限制 时间范围 30天前到现在
if (Objects.equals(searchDTO.getSort(), "createTime")) {
// 当前时间
final String nowStr = DateUtils.getTime();
// 当前时间往前推30天获取当天的0点0分0秒
LocalDateTime ago = LocalDateTime.now().minusDays(30).withHour(0).withMinute(0).withSecond(0);
// ago 转化为 yyyy-MM-dd HH:mm:ss
String agoStr = ago.format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS));
RangeQuery.Builder rangeBuilder = new RangeQuery.Builder();
rangeBuilder.date(DateRangeQuery.of(d -> d.field("createTime").gte(agoStr).lte(nowStr)));
boolQueryBuilder.filter(rangeBuilder.build()._toQuery());
}
// 构建最终的 bool query
BoolQuery boolQuery = boolQueryBuilder.build();
// 构建最终的查询
Query query = new Query.Builder().bool(boolQuery).build();
// 执行搜索
SearchResponse<ESProductDTO> resList = esClientWrapper.getEsClient()
.search(s -> s.index(ES_INDEX_NAME)
.query(query)
.from((searchDTO.getPageNum() - 1) * searchDTO.getPageSize())
.size(searchDTO.getPageSize())
.sort(Arrays.asList(
SortOptions.of(so -> so.field(f -> f.field(searchDTO.getSort()).order(searchDTO.getOrder()))),
SortOptions.of(so -> so.field(f -> f.field("storeWeight").order(SortOrder.Desc)))
)),
ESProductDTO.class);
final long total = resList.hits().total().value();
final List<ESProductDTO> esProdList = resList.hits().hits().stream().map(x -> x.source().setStoreProdId(x.id())).collect(Collectors.toList());
return new Page<>(searchDTO.getPageNum(), searchDTO.getPageSize(), total / searchDTO.getPageSize() + 1, total, esProdList);
*/
return this.esService.search(searchDTO);
}
/**
@ -1051,13 +882,5 @@ public class WebsitePCServiceImpl implements IWebsitePCService {
redisCache.setCacheObject(CacheConstants.USER_SEARCH_HISTORY + loginUser.getUserId(), userSearchList);
}
// 判断是否为中文字符
private boolean isChineseCharacter(String str) {
if (str == null || str.length() != 1) {
return false;
}
char c = str.charAt(0);
return (c >= '\u4e00' && c <= '\u9fa5');
}
}