搜索推荐引擎 - 让用户秒找心仪商品的智能大脑
# 搜索推荐引擎 - 让用户秒找心仪商品的智能大脑
# 📖 故事继续
小明在商品目录页面看到了琳琅满目的手表,但面对数百款选择,他有些眼花缭乱。于是他在搜索框输入了"瑞士 自动机械 防水",瞬间页面就筛选出了20多款符合条件的手表。更神奇的是,系统还在页面右侧推荐了"您可能还喜欢"的商品,包括手表配件、同品牌的其他产品,甚至还有根据他浏览历史推荐的相似风格商品。
小红是小明的女朋友,她经常在这个平台购买化妆品。当她登录平台时,首页就展示了最新的口红新品、她关注品牌的促销信息,以及基于她购买历史的个性化推荐。这一切看似魔法般的体验,背后是一套复杂而精密的搜索推荐引擎在默默工作。
今天,我们就来揭秘这个让用户"秒找心仪商品"的智能大脑是如何工作的。
# 🎯 系统概述
搜索推荐引擎是跨境电商平台的核心竞争力之一,它需要在毫秒级时间内从海量商品中找到用户最想要的结果。系统不仅要支持传统的关键词搜索,还要具备智能纠错、同义词识别、多语言搜索、个性化推荐等高级功能。
# 核心功能
- 全文搜索与筛选
- 智能查询理解
- 个性化推荐
- 实时热搜统计
- A/B测试支持
- 搜索结果排序优化
# 🏗️ 系统架构设计
# 整体架构图
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 用户界面 │ │ 搜索网关 │ │ 查询理解服务 │
│ │────│ │────│ │
│ - 搜索框 │ │ - 查询预处理 │ │ - 意图识别 │
│ - 筛选器 │ │ - 限流控制 │ │ - 查询扩展 │
│ - 结果展示 │ │ - 缓存管理 │ │ - 同义词处理 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
┌─────────────────┐ ┌─────────────────┐
│ 推荐引擎 │ │ 搜索引擎 │
│ │ │ │
│ - 协同过滤 │ │ - Elasticsearch │
│ - 内容推荐 │ │ - 倒排索引 │
│ - 深度学习 │ │ - 相关性评分 │
└─────────────────┘ └─────────────────┘
│
┌─────────────────┐
│ 数据存储层 │
│ │
│ - 商品索引 │
│ - 用户行为数据 │
│ - 推荐模型 │
│ - 搜索日志 │
└─────────────────┘
# 💻 核心代码实现
# 1. 搜索服务核心实现
/**
* 搜索服务核心实现类
* 职责:处理用户搜索请求,整合搜索和推荐结果
*/
@Service
public class SearchService {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private QueryUnderstandingService queryUnderstandingService;
@Autowired
private RecommendationService recommendationService;
@Autowired
private SearchMetricsService metricsService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 执行搜索请求
*
* @param request 搜索请求参数
* @return 搜索结果
*/
public SearchResponse search(SearchRequest request) {
// 1. 记录搜索开始时间(用于性能监控)
long startTime = System.currentTimeMillis();
try {
// 2. 查询理解和预处理
ProcessedQuery processedQuery = queryUnderstandingService.processQuery(request);
// 3. 构建搜索响应
SearchResponse response = new SearchResponse();
// 4. 执行主搜索
SearchResult mainSearchResult = executeMainSearch(processedQuery);
response.setMainResult(mainSearchResult);
// 5. 获取推荐结果(异步执行)
CompletableFuture<RecommendationResult> recommendationFuture =
CompletableFuture.supplyAsync(() ->
recommendationService.getRecommendations(request.getUserId(), processedQuery));
// 6. 获取相关搜索建议
List<String> suggestions = getSuggestions(processedQuery.getOriginalQuery());
response.setSuggestions(suggestions);
// 7. 等待推荐结果并设置
try {
RecommendationResult recommendations = recommendationFuture.get(100, TimeUnit.MILLISECONDS);
response.setRecommendations(recommendations);
} catch (TimeoutException e) {
log.warn("推荐服务超时,使用默认推荐");
response.setRecommendations(getDefaultRecommendations());
}
// 8. 记录搜索指标
long duration = System.currentTimeMillis() - startTime;
metricsService.recordSearch(request, response, duration);
return response;
} catch (Exception e) {
log.error("搜索执行失败", e);
metricsService.recordSearchError(request, e);
throw new SearchException("搜索服务异常: " + e.getMessage());
}
}
/**
* 执行主搜索逻辑
* 核心算法:多字段搜索 + 权重计算 + 结果排序
*/
private SearchResult executeMainSearch(ProcessedQuery processedQuery) {
// 1. 构建Elasticsearch查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 2. 主查询:多字段匹配
if (StringUtils.hasText(processedQuery.getProcessedQuery())) {
// 2.1 构建多字段查询
MultiMatchQueryBuilder multiMatchQuery = QueryBuilders
.multiMatchQuery(processedQuery.getProcessedQuery())
.field("name", 3.0f) // 商品名称权重最高
.field("description", 1.0f) // 描述权重中等
.field("brand", 2.0f) // 品牌权重较高
.field("category", 1.5f) // 分类权重中等
.field("tags", 1.2f) // 标签权重中等
.type(MultiMatchQueryBuilder.Type.BEST_FIELDS)
.fuzziness(Fuzziness.AUTO); // 自动模糊匹配
boolQuery.must(multiMatchQuery);
}
// 3. 筛选条件
addFilters(boolQuery, processedQuery.getFilters());
// 4. 构建搜索请求
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(boolQuery)
.from(processedQuery.getOffset())
.size(processedQuery.getSize())
.timeout(TimeValue.timeValueMillis(500)); // 500ms超时
// 5. 添加排序
addSorting(searchSourceBuilder, processedQuery.getSortOptions());
// 6. 添加聚合(用于筛选器统计)
addAggregations(searchSourceBuilder);
// 7. 添加高亮
addHighlighting(searchSourceBuilder);
// 8. 执行搜索
SearchRequest searchRequest = new SearchRequest("products")
.source(searchSourceBuilder);
try {
SearchResponse elasticResponse = elasticsearchTemplate.search(searchRequest, RequestOptions.DEFAULT);
return convertToSearchResult(elasticResponse, processedQuery);
} catch (Exception e) {
log.error("Elasticsearch查询失败", e);
throw new SearchException("搜索引擎查询失败");
}
}
/**
* 添加筛选条件
*/
private void addFilters(BoolQueryBuilder boolQuery, Map<String, Object> filters) {
filters.forEach((key, value) -> {
switch (key) {
case "category":
if (value instanceof List) {
boolQuery.filter(QueryBuilders.termsQuery("categoryId", (List<?>) value));
} else {
boolQuery.filter(QueryBuilders.termQuery("categoryId", value));
}
break;
case "brand":
if (value instanceof List) {
boolQuery.filter(QueryBuilders.termsQuery("brandId", (List<?>) value));
} else {
boolQuery.filter(QueryBuilders.termQuery("brandId", value));
}
break;
case "priceRange":
if (value instanceof Map) {
Map<String, Object> priceRange = (Map<String, Object>) value;
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("basePrice");
if (priceRange.containsKey("min")) {
rangeQuery.gte(priceRange.get("min"));
}
if (priceRange.containsKey("max")) {
rangeQuery.lte(priceRange.get("max"));
}
boolQuery.filter(rangeQuery);
}
break;
case "inStock":
if (Boolean.TRUE.equals(value)) {
boolQuery.filter(QueryBuilders.rangeQuery("stockQuantity").gt(0));
}
break;
default:
log.warn("未知的筛选条件: {}", key);
}
});
// 默认只显示上架商品
boolQuery.filter(QueryBuilders.termQuery("status", "ACTIVE"));
}
/**
* 添加排序逻辑
*/
private void addSorting(SearchSourceBuilder searchSourceBuilder, List<SortOption> sortOptions) {
if (sortOptions == null || sortOptions.isEmpty()) {
// 默认排序:相关性 + 销量 + 评分
searchSourceBuilder
.sort(SortBuilders.scoreSort().order(SortOrder.DESC)) // 相关性评分
.sort(SortBuilders.fieldSort("salesCount").order(SortOrder.DESC)) // 销量
.sort(SortBuilders.fieldSort("rating").order(SortOrder.DESC)); // 评分
return;
}
for (SortOption option : sortOptions) {
switch (option.getField()) {
case "price":
searchSourceBuilder.sort(SortBuilders.fieldSort("basePrice")
.order(option.isAscending() ? SortOrder.ASC : SortOrder.DESC));
break;
case "sales":
searchSourceBuilder.sort(SortBuilders.fieldSort("salesCount")
.order(SortOrder.DESC)); // 销量总是降序
break;
case "rating":
searchSourceBuilder.sort(SortBuilders.fieldSort("rating")
.order(SortOrder.DESC)); // 评分总是降序
break;
case "newest":
searchSourceBuilder.sort(SortBuilders.fieldSort("createdAt")
.order(SortOrder.DESC)); // 最新总是降序
break;
default:
log.warn("未知的排序字段: {}", option.getField());
}
}
}
/**
* 添加聚合统计(用于筛选器)
*/
private void addAggregations(SearchSourceBuilder searchSourceBuilder) {
// 品牌聚合
TermsAggregationBuilder brandAgg = AggregationBuilders
.terms("brands")
.field("brandId")
.size(50);
// 分类聚合
TermsAggregationBuilder categoryAgg = AggregationBuilders
.terms("categories")
.field("categoryId")
.size(20);
// 价格区间聚合
RangeAggregationBuilder priceRangeAgg = AggregationBuilders
.range("priceRanges")
.field("basePrice")
.addRange("0-50", 0, 50)
.addRange("50-100", 50, 100)
.addRange("100-200", 100, 200)
.addRange("200-500", 200, 500)
.addRange("500+", 500, Double.MAX_VALUE);
searchSourceBuilder
.aggregation(brandAgg)
.aggregation(categoryAgg)
.aggregation(priceRangeAgg);
}
/**
* 添加搜索结果高亮
*/
private void addHighlighting(SearchSourceBuilder searchSourceBuilder) {
HighlightBuilder highlightBuilder = new HighlightBuilder()
.field("name")
.field("description")
.preTags("<em class='highlight'>")
.postTags("</em>")
.fragmentSize(100)
.numOfFragments(3);
searchSourceBuilder.highlighter(highlightBuilder);
}
}
# 2. 查询理解服务
/**
* 查询理解服务
* 职责:对用户输入进行智能处理,提升搜索准确性
*/
@Service
public class QueryUnderstandingService {
@Autowired
private SynonymService synonymService;
@Autowired
private SpellCheckService spellCheckService;
@Autowired
private IntentRecognitionService intentRecognitionService;
/**
* 处理用户查询
* 核心流程:拼写纠错 → 同义词扩展 → 意图识别 → 查询重写
*/
public ProcessedQuery processQuery(SearchRequest request) {
String originalQuery = request.getQuery();
log.info("开始处理查询: {}", originalQuery);
ProcessedQuery processedQuery = new ProcessedQuery();
processedQuery.setOriginalQuery(originalQuery);
processedQuery.setUserId(request.getUserId());
processedQuery.setLanguage(request.getLanguage());
processedQuery.setFilters(request.getFilters());
processedQuery.setOffset(request.getOffset());
processedQuery.setSize(request.getSize());
processedQuery.setSortOptions(request.getSortOptions());
// 1. 查询预处理
String cleanedQuery = preprocessQuery(originalQuery);
// 2. 拼写检查和纠错
String correctedQuery = spellCheckService.correctSpelling(cleanedQuery, request.getLanguage());
if (!cleanedQuery.equals(correctedQuery)) {
processedQuery.setSpellCorrected(true);
processedQuery.setSuggestedQuery(correctedQuery);
log.info("拼写纠错: {} → {}", cleanedQuery, correctedQuery);
}
// 3. 同义词扩展
String expandedQuery = synonymService.expandQuery(correctedQuery, request.getLanguage());
// 4. 意图识别
QueryIntent intent = intentRecognitionService.recognizeIntent(expandedQuery, request);
processedQuery.setIntent(intent);
// 5. 根据意图调整查询
String finalQuery = adjustQueryByIntent(expandedQuery, intent);
processedQuery.setProcessedQuery(finalQuery);
// 6. 提取查询特征(用于个性化)
extractQueryFeatures(processedQuery, originalQuery);
log.info("查询处理完成: {} → {}", originalQuery, finalQuery);
return processedQuery;
}
/**
* 查询预处理
* 清理特殊字符、标准化格式
*/
private String preprocessQuery(String query) {
if (StringUtils.isEmpty(query)) {
return "";
}
return query
.trim() // 去除首尾空格
.toLowerCase() // 转小写
.replaceAll("[^\\w\\s\\u4e00-\\u9fa5]", " ") // 保留字母、数字、空格、中文
.replaceAll("\\s+", " ") // 多个空格合并为一个
.trim();
}
/**
* 根据意图调整查询
*/
private String adjustQueryByIntent(String query, QueryIntent intent) {
switch (intent.getType()) {
case BRAND_SEARCH:
// 品牌搜索:提升品牌字段权重
return query + "^brand:2.0";
case CATEGORY_SEARCH:
// 分类搜索:提升分类字段权重
return query + "^category:2.0";
case PRICE_SENSITIVE:
// 价格敏感:添加价格排序提示
return query + "^sort:price";
case FEATURE_SEARCH:
// 功能特性搜索:提升描述和特性字段权重
return query + "^description:1.5^features:1.5";
default:
return query;
}
}
/**
* 提取查询特征
*/
private void extractQueryFeatures(ProcessedQuery processedQuery, String originalQuery) {
Map<String, Object> features = new HashMap<>();
// 查询长度特征
features.put("queryLength", originalQuery.length());
features.put("wordCount", originalQuery.split("\\s+").length);
// 查询类型特征
features.put("hasNumbers", originalQuery.matches(".*\\d.*"));
features.put("hasChinese", originalQuery.matches(".*[\\u4e00-\\u9fa5].*"));
features.put("hasEnglish", originalQuery.matches(".*[a-zA-Z].*"));
// 商业意图特征
features.put("hasPriceKeywords", containsPriceKeywords(originalQuery));
features.put("hasBrandKeywords", containsBrandKeywords(originalQuery));
processedQuery.setFeatures(features);
}
private boolean containsPriceKeywords(String query) {
String[] priceKeywords = {"便宜", "贵", "价格", "多少钱", "cheap", "expensive", "price", "cost"};
return Arrays.stream(priceKeywords)
.anyMatch(keyword -> query.toLowerCase().contains(keyword));
}
private boolean containsBrandKeywords(String query) {
// 这里可以维护一个品牌关键词库
String[] brandKeywords = {"苹果", "三星", "华为", "apple", "samsung", "huawei", "nike", "adidas"};
return Arrays.stream(brandKeywords)
.anyMatch(keyword -> query.toLowerCase().contains(keyword));
}
}
# 3. 推荐引擎实现
/**
* 推荐引擎服务
* 实现多种推荐算法:协同过滤、内容推荐、深度学习推荐
*/
@Service
public class RecommendationService {
@Autowired
private UserBehaviorService userBehaviorService;
@Autowired
private ProductSimilarityService productSimilarityService;
@Autowired
private DeepLearningModelService deepLearningModelService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 获取推荐结果
* 策略:多路召回 + 融合排序
*/
public RecommendationResult getRecommendations(String userId, ProcessedQuery query) {
RecommendationResult result = new RecommendationResult();
try {
// 1. 多路召回
List<RecommendationCandidate> candidates = new ArrayList<>();
// 1.1 协同过滤召回
List<RecommendationCandidate> cfCandidates =
getCollaborativeFilteringRecommendations(userId, 50);
candidates.addAll(cfCandidates);
// 1.2 内容推荐召回
List<RecommendationCandidate> contentCandidates =
getContentBasedRecommendations(userId, query, 50);
candidates.addAll(contentCandidates);
// 1.3 热门商品召回
List<RecommendationCandidate> popularCandidates =
getPopularRecommendations(query.getLanguage(), 30);
candidates.addAll(popularCandidates);
// 1.4 深度学习模型召回
if (StringUtils.hasText(userId)) {
List<RecommendationCandidate> dlCandidates =
deepLearningModelService.getRecommendations(userId, 40);
candidates.addAll(dlCandidates);
}
// 2. 去重和融合排序
List<RecommendationItem> finalRecommendations =
mergeAndRankCandidates(candidates, userId, query);
// 3. 分组返回
result.setPersonalizedRecommendations(
finalRecommendations.stream()
.filter(item -> "PERSONALIZED".equals(item.getType()))
.limit(10)
.collect(Collectors.toList())
);
result.setSimilarProducts(
finalRecommendations.stream()
.filter(item -> "SIMILAR".equals(item.getType()))
.limit(8)
.collect(Collectors.toList())
);
result.setTrendingProducts(
finalRecommendations.stream()
.filter(item -> "TRENDING".equals(item.getType()))
.limit(6)
.collect(Collectors.toList())
);
} catch (Exception e) {
log.error("推荐服务异常", e);
// 降级处理:返回热门商品
result = getFallbackRecommendations();
}
return result;
}
/**
* 协同过滤推荐
* 算法:基于用户的协同过滤 + 基于物品的协同过滤
*/
private List<RecommendationCandidate> getCollaborativeFilteringRecommendations(
String userId, int limit) {
if (StringUtils.isEmpty(userId)) {
return Collections.emptyList();
}
// 1. 获取用户行为历史
UserBehaviorProfile userProfile = userBehaviorService.getUserProfile(userId);
// 2. 找到相似用户
List<String> similarUsers = findSimilarUsers(userId, userProfile, 100);
// 3. 获取相似用户喜欢的商品
Map<String, Double> productScores = new HashMap<>();
for (String similarUserId : similarUsers) {
UserBehaviorProfile similarProfile = userBehaviorService.getUserProfile(similarUserId);
double userSimilarity = calculateUserSimilarity(userProfile, similarProfile);
// 计算商品推荐分数
similarProfile.getLikedProducts().forEach((productId, score) -> {
if (!userProfile.getLikedProducts().containsKey(productId)) {
productScores.merge(productId, score * userSimilarity, Double::sum);
}
});
}
// 4. 排序并返回Top N
return productScores.entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.limit(limit)
.map(entry -> new RecommendationCandidate(
entry.getKey(),
entry.getValue(),
"COLLABORATIVE_FILTERING",
"因为购买了相似商品的用户也喜欢"
))
.collect(Collectors.toList());
}
/**
* 内容推荐
* 基于商品特征相似度推荐
*/
private List<RecommendationCandidate> getContentBasedRecommendations(
String userId, ProcessedQuery query, int limit) {
List<RecommendationCandidate> candidates = new ArrayList<>();
// 1. 基于用户历史行为的内容推荐
if (StringUtils.hasText(userId)) {
UserBehaviorProfile userProfile = userBehaviorService.getUserProfile(userId);
// 获取用户喜欢的商品特征
ProductFeatureProfile featureProfile = extractUserFeaturePreference(userProfile);
// 基于特征相似度推荐
List<String> similarProducts = productSimilarityService
.findSimilarProductsByFeatures(featureProfile, limit / 2);
similarProducts.forEach(productId -> {
double score = calculateContentSimilarityScore(featureProfile, productId);
candidates.add(new RecommendationCandidate(
productId, score, "CONTENT_BASED", "基于您的偏好推荐"
));
});
}
// 2. 基于当前搜索的内容推荐
if (StringUtils.hasText(query.getProcessedQuery())) {
List<String> relatedProducts = productSimilarityService
.findProductsByQuery(query.getProcessedQuery(), limit / 2);
relatedProducts.forEach(productId -> {
double score = calculateQueryRelevanceScore(query, productId);
candidates.add(new RecommendationCandidate(
productId, score, "QUERY_RELATED", "与搜索内容相关"
));
});
}
return candidates;
}
/**
* 融合排序算法
* 综合考虑多种因素:推荐分数、商品质量、用户偏好、业务策略
*/
private List<RecommendationItem> mergeAndRankCandidates(
List<RecommendationCandidate> candidates, String userId, ProcessedQuery query) {
// 1. 去重(同一商品可能来自多个召回源)
Map<String, RecommendationCandidate> uniqueCandidates = new HashMap<>();
for (RecommendationCandidate candidate : candidates) {
String productId = candidate.getProductId();
if (uniqueCandidates.containsKey(productId)) {
// 如果已存在,取最高分数
RecommendationCandidate existing = uniqueCandidates.get(productId);
if (candidate.getScore() > existing.getScore()) {
uniqueCandidates.put(productId, candidate);
}
} else {
uniqueCandidates.put(productId, candidate);
}
}
// 2. 计算最终排序分数
List<RecommendationItem> rankedItems = uniqueCandidates.values().stream()
.map(candidate -> {
double finalScore = calculateFinalScore(candidate, userId, query);
return new RecommendationItem(
candidate.getProductId(),
finalScore,
determineRecommendationType(candidate),
candidate.getReason()
);
})
.sorted(Comparator.comparingDouble(RecommendationItem::getScore).reversed())
.limit(50) // 最多返回50个推荐
.collect(Collectors.toList());
return rankedItems;
}
/**
* 计算最终推荐分数
* 综合算法:基础分数 × 商品质量分数 × 个性化分数 × 业务权重
*/
private double calculateFinalScore(RecommendationCandidate candidate,
String userId, ProcessedQuery query) {
double baseScore = candidate.getScore();
// 1. 商品质量分数(评分、销量、库存等)
double qualityScore = getProductQualityScore(candidate.getProductId());
// 2. 个性化分数(用户偏好匹配度)
double personalizationScore = getPersonalizationScore(candidate.getProductId(), userId);
// 3. 时效性分数(新品、热门等)
double freshnessScore = getFreshnessScore(candidate.getProductId());
// 4. 业务策略分数(利润率、库存周转等)
double businessScore = getBusinessScore(candidate.getProductId());
// 5. 多样性惩罚(避免推荐过于相似的商品)
double diversityPenalty = getDiversityPenalty(candidate.getProductId(), query);
// 综合计算最终分数
double finalScore = baseScore * 0.4 + // 基础推荐分数权重40%
qualityScore * 0.25 + // 商品质量权重25%
personalizationScore * 0.2 + // 个性化权重20%
freshnessScore * 0.1 + // 时效性权重10%
businessScore * 0.05; // 业务策略权重5%
// 应用多样性惩罚
finalScore *= (1.0 - diversityPenalty);
return Math.max(0.0, Math.min(1.0, finalScore)); // 确保分数在[0,1]范围内
}
/**
* 获取商品质量分数
*/
private double getProductQualityScore(String productId) {
// 这里可以从缓存或数据库获取商品质量指标
// 包括:用户评分、销量、退货率、库存状态等
// 示例实现
String cacheKey = "product:quality:" + productId;
Double cachedScore = (Double) redisTemplate.opsForValue().get(cacheKey);
if (cachedScore != null) {
return cachedScore;
}
// 计算质量分数的逻辑
double rating = getProductRating(productId); // 用户评分 (1-5)
int salesCount = getProductSalesCount(productId); // 销量
double returnRate = getProductReturnRate(productId); // 退货率
boolean inStock = isProductInStock(productId); // 库存状态
double qualityScore = (rating / 5.0) * 0.4 + // 评分权重40%
Math.min(1.0, salesCount / 1000.0) * 0.3 + // 销量权重30%
(1.0 - returnRate) * 0.2 + // 退货率权重20%
(inStock ? 1.0 : 0.5) * 0.1; // 库存权重10%
// 缓存结果(1小时过期)
redisTemplate.opsForValue().set(cacheKey, qualityScore, Duration.ofHours(1));
return qualityScore;
}
// 其他辅助方法的实现...
private double getProductRating(String productId) { return 4.2; }
private int getProductSalesCount(String productId) { return 500; }
private double getProductReturnRate(String productId) { return 0.05; }
private boolean isProductInStock(String productId) { return true; }
private double getPersonalizationScore(String productId, String userId) { return 0.8; }
private double getFreshnessScore(String productId) { return 0.7; }
private double getBusinessScore(String productId) { return 0.6; }
private double getDiversityPenalty(String productId, ProcessedQuery query) { return 0.1; }
}
# 🔧 技术要点解析
# 1. Elasticsearch索引设计
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"description": {
"type": "text",
"analyzer": "ik_max_word"
},
"brand": {
"type": "keyword"
},
"category": {
"type": "keyword"
},
"tags": {
"type": "keyword"
},
"basePrice": {
"type": "double"
},
"rating": {
"type": "double"
},
"salesCount": {
"type": "integer"
},
"stockQuantity": {
"type": "integer"
},
"status": {
"type": "keyword"
},
"createdAt": {
"type": "date"
},
"features": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "text"
}
}
}
}
},
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"ik_max_word": {
"type": "ik_max_word"
},
"ik_smart": {
"type": "ik_smart"
}
}
}
}
}
# 2. 搜索性能优化
/**
* 搜索性能优化配置
*/
@Configuration
public class SearchOptimizationConfig {
/**
* 搜索线程池配置
*/
@Bean("searchExecutor")
public ThreadPoolTaskExecutor searchExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("search-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
/**
* 搜索缓存配置
*/
@Bean
public CacheManager searchCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(Duration.ofMinutes(10))
.recordStats());
return cacheManager;
}
}
# 📊 监控与分析
# 1. 搜索指标监控
/**
* 搜索指标服务
*/
@Service
public class SearchMetricsService {
private final Counter searchCounter;
private final Timer searchTimer;
private final Counter clickCounter;
private final Gauge cacheHitRate;
public SearchMetricsService(MeterRegistry meterRegistry) {
this.searchCounter = Counter.builder("search.requests.total")
.description("搜索请求总数")
.register(meterRegistry);
this.searchTimer = Timer.builder("search.duration")
.description("搜索耗时")
.register(meterRegistry);
this.clickCounter = Counter.builder("search.clicks.total")
.description("搜索结果点击数")
.register(meterRegistry);
}
public void recordSearch(SearchRequest request, SearchResponse response, long duration) {
searchCounter.increment(
Tags.of(
"query_type", determineQueryType(request.getQuery()),
"result_count", String.valueOf(response.getMainResult().getTotal()),
"has_results", String.valueOf(response.getMainResult().getTotal() > 0)
)
);
searchTimer.record(duration, TimeUnit.MILLISECONDS);
}
public void recordClick(String query, String productId, int position) {
clickCounter.increment(
Tags.of(
"position", String.valueOf(position),
"page", String.valueOf(position / 20 + 1)
)
);
}
}
# 🎉 总结
通过本文的深入学习,我们全面了解了跨境电商搜索推荐引擎的设计与实现。从小明输入"瑞士手表"到获得精准的搜索结果和个性化推荐,背后是一套复杂而精密的技术体系在支撑。
# 关键收获
- 搜索架构:多层次的搜索架构设计,支持高并发和高可用
- 查询理解:智能的查询预处理,提升搜索准确性
- 推荐算法:多种推荐算法的融合,提供个性化体验
- 性能优化:缓存策略、索引优化、异步处理等技术手段
- 监控分析:完善的指标监控和数据分析体系
# 最佳实践
- 采用Elasticsearch构建高性能搜索引擎
- 实现多路召回和融合排序的推荐策略
- 使用多级缓存提升系统响应速度
- 建立完善的A/B测试和效果评估体系
- 重视用户体验,提供智能的搜索建议和纠错
# 技术演进方向
- AI增强:集成更先进的NLP和深度学习模型
- 实时性:构建实时的用户行为分析和推荐系统
- 个性化:更精细的用户画像和个性化推荐
- 多模态:支持图像、语音等多模态搜索
下一篇文章,我们将继续探讨跨境电商交易链路的下一个关键环节:购物车系统,看看如何设计一个高性能、高可用的购物车服务。