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

相关推荐
在未来等你3 小时前
Elasticsearch面试精讲 Day 16:索引性能优化策略
大数据·分布式·elasticsearch·搜索引擎·面试
咖啡Beans5 小时前
SpringBoot集成ELK实现数据存储和日志管理
spring boot·elasticsearch·kibana
*老工具人了*5 小时前
Terraform整合到GitLab+Jenkins工具链
gitlab·jenkins·terraform
码畜也有梦想6 小时前
Maven中optional的作用
java·jenkins·maven
Ttang238 小时前
ES+MySQL实时搜索架构实战解析
mysql·elasticsearch·架构
AIbase202413 小时前
AI技术架构与GEO算法原理如何重塑搜索引擎可见性
人工智能·搜索引擎·架构
Elastic 中国社区官方博客20 小时前
带地图的 RAG:多模态 + 地理空间 在 Elasticsearch 中
大数据·人工智能·elasticsearch·搜索引擎·ai·语言模型·全文检索
阿里云大数据AI技术21 小时前
AI搜索的黑科技?DeepSearch 究竟“深”藏着什么秘密?
搜索引擎
qq_356408661 天前
es通过分片迁移迁移解决磁盘不均匀问题
java·数据库·elasticsearch