电商导购平台的搜索引擎优化:基于Elasticsearch的商品精准推荐系统
电商导购平台的搜索引擎优化:基于Elasticsearch的商品精准推荐系统
大家好,我是阿可,微赚淘客系统及省赚客APP创始人,是个冬天不穿秋裤,天冷也要风度的程序猿!
在电商导购平台中,用户能否快速找到目标商品,直接决定了转化效率。而 Elasticsearch 作为分布式全文检索引擎,凭借高吞吐量、灵活的分词能力和精准的评分机制,成为构建商品搜索与推荐系统的核心技术。下面从环境搭建、索引设计、搜索优化到个性化推荐,结合 Java 代码实现完整技术方案。
一、Elasticsearch 客户端集成(Spring Boot 环境)
首先需在项目中引入 Elasticsearch 依赖,并配置 RestHighLevelClient 客户端,实现与 ES 集群的连接:
<!-- pom.xml 依赖配置 -->
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.17.0</version>
</dependency>
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 {@Beanpublic 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);}
}
二、商品索引结构设计(适配导购场景)
电商导购场景需支持“关键词检索、分类过滤、价格排序、销量权重”,因此索引需合理定义字段类型与分词策略,代码如下:
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 {@Autowiredprivate 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());}
}
三、核心搜索逻辑实现(关键词+过滤+排序)
结合导购平台用户需求,实现“关键词检索+多条件过滤+权重排序”的搜索功能,代码如下:
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 {@Autowiredprivate 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);}
}
四、个性化推荐:基于用户行为的权重调整
通过用户历史浏览、收藏、购买记录,动态调整搜索结果权重,提升推荐精准度,代码如下:
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 {@Autowiredprivate 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开发者团队,转载请注明出处!