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

相关推荐
会飞的小蛮猪1 天前
ELK运维之路(使用Logstatsh对日志进行处理综合案例)
elasticsearch·自动化运维·logstash
catoop1 天前
Jenkins Pipeline 中使用 GitLab Webhook 触发任务执行
jenkins
Gss7771 天前
Jenkins流水线项目发布
运维·jenkins
爱学习的爬虫1 天前
Python实现Jenkins实现自动化执行Job
python·自动化·jenkins
lang201509281 天前
Spring Boot Actuator应用信息Application Information全解析
spring boot·后端·elasticsearch
三口吃掉你1 天前
Docker安装Elasticsearch、kibana、IK分词器
elasticsearch·docker·kibana·ik分词器
dehuisun1 天前
jenkins流水线部署springboot项目
运维·jenkins
神秘人X7072 天前
Jenkins 持续集成与部署指南
运维·ci/cd·jenkins
一棵树73512 天前
Android OpenGL ES初窥
android·大数据·elasticsearch
_李小白2 天前
【OPENGL ES 3.0 学习笔记】第九天:缓存、顶点和顶点数组
笔记·学习·elasticsearch