电商导购平台的搜索引擎优化:基于Elasticsearch的商品精准推荐系统
大家好,我是阿可,微赚淘客系统及省赚客APP创始人,是个冬天不穿秋裤,天冷也要风度的程序猿!
在电商导购平台中,用户能否快速找到目标商品,直接决定了转化效率。而 Elasticsearch 作为分布式全文检索引擎,凭借高吞吐量、灵活的分词能力和精准的评分机制,成为构建商品搜索与推荐系统的核心技术。下面从环境搭建、索引设计、搜索优化到个性化推荐,结合 Java 代码实现完整技术方案。

一、Elasticsearch 客户端集成(Spring Boot 环境)
首先需在项目中引入 Elasticsearch 依赖,并配置 RestHighLevelClient 客户端,实现与 ES 集群的连接:
xml
<!-- pom.xml 依赖配置 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.0</version>
</dependency>
java
package cn.juwatech.elasticsearch.config;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClient;
import java.util.Collections;
@Configuration
public class EsClientConfig {
@Bean
public RestHighLevelClient esRestClient() {
// 配置 ES 集群节点,支持多节点容错
RestClientBuilder builder = RestClient.builder(
new HttpHost("10.0.0.10", 9200, "http"),
new HttpHost("10.0.0.11", 9200, "http")
);
// 配置连接池与超时参数
builder.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultHeaders(Collections.singletonList(
new BasicHeader("Content-Type", "application/json")
)).setConnectTimeout(3000)
.setSocketTimeout(5000));
return new RestHighLevelClient(builder);
}
}
二、商品索引结构设计(适配导购场景)
电商导购场景需支持"关键词检索、分类过滤、价格排序、销量权重",因此索引需合理定义字段类型与分词策略,代码如下:
java
package cn.juwatech.elasticsearch.service;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public class EsIndexService {
@Autowired
private RestHighLevelClient esClient;
// 创建商品索引(product_index)
public void createProductIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("product_index");
// 构建索引映射(Mapping)
XContentBuilder mapping = XContentFactory.jsonBuilder()
.startObject()
.startObject("properties")
// 商品ID(精确匹配,用于唯一标识)
.startObject("productId")
.field("type", "keyword")
.endObject()
// 商品名称(IK分词,支持模糊检索)
.startObject("productName")
.field("type", "text")
.field("analyzer", "ik_max_word") // 索引时分词更细
.field("search_analyzer", "ik_smart") // 搜索时分词更粗
.startObject("fields")
.field("keyword", "keyword") // 支持按名称排序
.endObject()
.endObject()
// 商品分类ID(整数类型,用于过滤)
.startObject("categoryId")
.field("type", "integer")
.endObject()
// 商品价格(浮点型,支持范围查询与排序)
.startObject("price")
.field("type", "double")
.endObject()
// 商品销量(整数型,用于权重排序)
.startObject("salesCount")
.field("type", "integer")
.endObject()
// 商品标签(数组类型,支持多标签过滤)
.startObject("tags")
.field("type", "keyword")
.endObject()
.endObject()
.endObject();
// 设置索引分片与副本(3主1副,适配中等数据量)
request.settings(Settings.builder()
.put("index.number_of_shards", 3)
.put("index.number_of_replicas", 1));
request.mapping(mapping);
CreateIndexResponse response = esClient.indices().create(request, RequestOptions.DEFAULT);
System.out.println("索引创建状态:" + response.isAcknowledged());
}
}
三、核心搜索逻辑实现(关键词+过滤+排序)
结合导购平台用户需求,实现"关键词检索+多条件过滤+权重排序"的搜索功能,代码如下:
java
package cn.juwatech.elasticsearch.service;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public class EsSearchService {
@Autowired
private RestHighLevelClient esClient;
/**
* 商品搜索方法
* @param keyword 搜索关键词
* @param categoryId 分类ID(可选)
* @param minPrice 最低价格(可选)
* @param maxPrice 最高价格(可选)
* @param tags 标签列表(可选)
* @param page 页码(从1开始)
* @param size 每页条数
*/
public SearchResponse searchProducts(String keyword, Integer categoryId,
Double minPrice, Double maxPrice,
String[] tags, Integer page, Integer size) throws IOException {
SearchRequest request = new SearchRequest("product_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 1. 关键词匹配(商品名称,提升匹配权重)
if (keyword != null && !keyword.trim().isEmpty()) {
boolQuery.should(QueryBuilders.matchQuery("productName", keyword).boost(2.0f))
.should(QueryBuilders.matchPhraseQuery("productName", keyword).slop(1).boost(3.0f));
}
// 2. 分类过滤(精确匹配)
if (categoryId != null) {
boolQuery.filter(QueryBuilders.termQuery("categoryId", categoryId));
}
// 3. 价格范围过滤
if (minPrice != null || maxPrice != null) {
BoolQueryBuilder priceQuery = QueryBuilders.boolQuery();
if (minPrice != null) {
priceQuery.filter(QueryBuilders.rangeQuery("price").gte(minPrice));
}
if (maxPrice != null) {
priceQuery.filter(QueryBuilders.rangeQuery("price").lte(maxPrice));
}
boolQuery.filter(priceQuery);
}
// 4. 标签过滤(多标签匹配)
if (tags != null && tags.length > 0) {
boolQuery.filter(QueryBuilders.termsQuery("tags", tags));
}
// 5. 排序规则:销量降序 > 价格升序(满足用户"高销量+性价比"需求)
sourceBuilder.sort("salesCount", SortOrder.DESC);
sourceBuilder.sort("price", SortOrder.ASC);
// 6. 分页配置(避免深分页性能问题)
sourceBuilder.from((page - 1) * size);
sourceBuilder.size(size);
sourceBuilder.query(boolQuery);
request.source(sourceBuilder);
return esClient.search(request, RequestOptions.DEFAULT);
}
}
四、个性化推荐:基于用户行为的权重调整
通过用户历史浏览、收藏、购买记录,动态调整搜索结果权重,提升推荐精准度,代码如下:
java
package cn.juwatech.elasticsearch.service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PersonalRecommendService {
@Autowired
private UserBehaviorService userBehaviorService; // 用户行为服务(自定义)
/**
* 为搜索结果添加个性化权重
* @param sourceBuilder 搜索构建器
* @param userId 用户ID
*/
public void addPersonalWeight(SearchSourceBuilder sourceBuilder, Long userId) {
// 1. 获取用户历史行为数据
List<Integer> collectedCategoryIds = userBehaviorService.getUserCollectedCategories(userId); // 收藏分类
List<String> historyKeywords = userBehaviorService.getUserHistoryKeywords(userId); // 历史搜索词
BoolQueryBuilder boolQuery = (BoolQueryBuilder) sourceBuilder.query();
// 2. 对用户收藏分类的商品提升权重(×1.5)
if (collectedCategoryIds != null && !collectedCategoryIds.isEmpty()) {
for (Integer categoryId : collectedCategoryIds) {
boolQuery.should(QueryBuilders.termQuery("categoryId", categoryId).boost(1.5f));
}
}
// 3. 对用户历史搜索词匹配的商品提升权重(×2.0)
if (historyKeywords != null && !historyKeywords.isEmpty()) {
for (String keyword : historyKeywords) {
boolQuery.should(QueryBuilders.matchQuery("productName", keyword).boost(2.0f));
}
}
sourceBuilder.query(boolQuery);
}
}
// 配套的用户行为服务(简化版)
package cn.juwatech.user.service;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserBehaviorService {
// 获取用户收藏的分类ID列表
public List<Integer> getUserCollectedCategories(Long userId) {
// 实际场景从MySQL/Redis查询,此处模拟数据
return List.of(201, 203); // 示例:用户收藏"女装""鞋包"分类
}
// 获取用户历史搜索词列表
public List<String> getUserHistoryKeywords(Long userId) {
// 实际场景从MySQL/Redis查询,此处模拟数据
return List.of("加绒卫衣", "马丁靴"); // 示例:用户历史搜索词
}
}
本文著作权归聚娃科技省赚客app开发者团队,转载请注明出处!