电商导购平台的搜索引擎优化:基于Elasticsearch的商品精准推荐系统

电商导购平台的搜索引擎优化:基于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开发者团队,转载请注明出处!

相关推荐
ofoxcoding20 小时前
借助 CLAUDE.md 约束 Sonnet 5.5 多文件重构行为的提示词实践
大数据·elasticsearch·ai·重构
Elasticsearch20 小时前
隆重推出 AlertZero:让你的告警队列实现 “收件箱清零” 式管理
elasticsearch
ly768921 小时前
从 TF-IDF 到 BM25:Elasticsearch 相关性评分的字段长度归一化与 boost 调参边界
java·elasticsearch·query dsl·bm25·相关性评分
SL-staff21 小时前
技术实践:将Excel自动升级为可搜索的知识节点(JVS平台实现)
mongodb·elasticsearch·知识图谱·jvs平台·语义解析·企业文档管理·excel结构化
Elasticsearch21 小时前
2026 年唯一获得端点预防与响应(EPR)满分的厂商是 Elastic
elasticsearch
vx_Biye_Design21 小时前
springboot旅游管理系统18006-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·django·课程设计
ly76891 天前
倒排索引与 FST 在 Lucene 中的内存布局:segment、docValues 与词典压缩的工程取舍
elasticsearch·lucene·倒排索引·doc values·fst
Elasticsearch1 天前
利用预计算上下文,更快速、更低成本地开展支持问题调查
elasticsearch
小小小米粒1 天前
重置本地git
大数据·git·elasticsearch
ly76891 天前
Spring Boot 集成 Elasticsearch 的生产实践:客户端选型、索引生命周期与批量写入容错
spring boot·elasticsearch·索引生命周期·java api client·批量写入