当前位置: 首页 > news >正文

SpringBoot集成RedisSearch

文章目录

  • 1.背景
  • 2.安装redisSearch
  • 3.添加Maven依赖
  • 4.配置类
  • 5.实体类和索引
    • 5.1 定义实体类
    • 5.2 创建索引(含地理字段)
  • 6.数据操作服务
  • 7.搜索功能实现
    • 7.1 基础搜索
    • 7.2 高级搜索功能
  • 8.测试

1.背景

Redis Search 是 Redis 官方提供的全文搜索引擎,它为Redis 提供全文搜索、索引和复杂查询功能。它基于内存存储,结合了 Redis 的高性能和倒排索引技术,支持实时搜索、聚合分析、模糊匹配等场景。RedisSearch 适用于需要快速检索结构化或非结构化数据的应用,如电商搜索、日志分析、实时推荐等。更多详细的介绍可参见:《一文了解亿级数据检索:RedisSearch》

2.安装redisSearch

本文不在赘述,详情可参见:《docker安装redisSearch》

3.添加Maven依赖

<dependencies>
    <!-- SpringBoot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- RedisSearch 核心依赖 -->
    <dependency>
        <groupId>com.redislabs</groupId>
        <artifactId>jredisearch</artifactId>
        <version>2.2.0</version>
        <exclusions>
            <exclusion>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    <!-- 适配 Redis 7.x 的 Jedis -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
</dependencies>

4.配置类

import io.redisearch.client.Client;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedisSearchConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Bean
    public Client redisSearchClient() {
        // 创建 RediSearch 客户端
        return new Client("productIndex", host, port);
    }
}

application.properties

spring.redis.host=127.0.0.1
spring.redis.port=6379

5.实体类和索引

5.1 定义实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import redis.clients.jedis.GeoCoordinate;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    private String id;
    private String title;
    private Double price;
    private String category;
    private GeoCoordinate location; // 地理位置坐标
}

5.2 创建索引(含地理字段)

import io.redisearch.Schema;
import io.redisearch.client.Client;
import io.redisearch.client.IndexDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class IndexService {
    @Autowired
    private Client client;

    public void createProductIndex() {
        Schema schema = new Schema()
                .addTextField("title", 5.0)   // 文本字段,权重5.0
                .addNumericField("price")     // 数值字段
                .addTagField("category")      // 标签字段
                .addGeoField("location");     // 地理字段

        IndexDefinition rule = new IndexDefinition(IndexDefinition.Type.HASH)
                .setPrefixes("product:");    // 自动索引以 product: 开头的键

        client.createIndex(schema, Client.IndexOptions.defaultOptions().setDefinition(rule));
    }
}

6.数据操作服务

import com.example.mapstuct.dto.Product;
import io.redisearch.Document;
import io.redisearch.client.Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class ProductService {
    @Autowired
    private Client client;

    // 添加文档
    public void addProduct(Product product) {
        Document doc = new Document("product:" + product.getId())
                .set("title", product.getTitle())
                .set("price", product.getPrice())
                .set("category", product.getCategory())
                .set("location", product.getLocation().getLongitude() + "," + product.getLocation().getLatitude());
        client.addDocument(doc);
    }

    // 更新文档
    public void updateProduct(String id, Double score, Map<String, Object> fields) {
        client.updateDocument("product:" + id, score, fields);
    }

    // 删除文档
    public void deleteProduct(String id) {
        client.deleteDocument("product:" + id);
    }
        public SearchResult searchProducts(String query) {
        return client.search(
                new Query(query)
                        .limit(0, 10)                // 分页
                        .setWithScores()              // 返回相关性评分
        );
    }

    public SearchResult searchProductsByQuery(Query query) {
        return client.search(query);
    }
}

7.搜索功能实现

7.1 基础搜索

public SearchResult searchProducts(String query) {
    return client.search(
        new Query(query)
            .limit(0, 10)                // 分页
            .setWithScores()              // 返回相关性评分
    );
}

7.2 高级搜索功能

// 高亮显示
Query query = new Query("蓝牙耳机")
    .highlight("title", "<b>", "</b>");  // 高亮标题字段中的匹配词[1](@ref)

// 通配符搜索
Query wildcardQuery = new Query("蓝*");    // 匹配“蓝牙”“蓝色”等[1](@ref)

// 布尔逻辑
Query boolQuery = new Query("耳机 AND -入耳式"); // 包含“耳机”且不包含“入耳式”[1](@ref)

// 范围查询
Query rangeQuery = new Query("@price:[200 500]"); // 价格区间过滤[1](@ref)

// 地理位置检索(100公里内)
Query geoQuery = new Query("@location:[经度 纬度 100 km]"); // 基于坐标的范围查询[23,24](@ref)

8.测试

@SpringBootTest
public class RedisSearchDemoTest {
    @Autowired
    private IndexService indexService;
    @Autowired
    private ProductService productService;

    @Test
    void fullDemoTest() {
        // 1. 创建索引
        indexService.createProductIndex();

        // 2. 添加数据
        Product p1 = new Product("1", "无线蓝牙耳机", 299.0, 
            "电子产品", new GeoCoordinate(116.397469, 39.908821));
        productService.addProduct(p1);

        // 3. 执行高级搜索
        SearchResult result = productService.searchProducts(
            "@category:{电子产品} @price:[200 300] @location:[116.397469 39.908821 10 km]"
        );

        // 4. 输出高亮结果
        result.getDocuments().forEach(doc -> 
            System.out.println("高亮标题:" + doc.get("title")));
    }
}

在这里插入图片描述

相关文章:

  • 深度学习|注意力机制
  • 【Java中级】11章、注解、元注解介绍、快速入门,了解java注解的基本使用方式【2】
  • vscode 跳转失败之c_cpp_properties.json解析
  • 【从一个 TypeScript 报错理解 ES6 模块的三种导入方式】
  • 北京自在科技:让万物接入苹果Find My网络的″钥匙匠″
  • sql-labs靶场 less-2
  • PyTorch张量范数计算终极指南:从基础到高阶实战
  • Python: sqlite3.OperationalError: no such table: ***解析
  • 在1panel中安装WebUI
  • 未来杭州:科技与诗意的时空交响曲
  • Linux 学习笔记(4):cd 与 pwd 命令的深度解析与实战应用(期末、期中复习必备)
  • ArcGis Reclassify CDL
  • muduo:运行起来
  • Prometheus采集容器故障排查
  • 从CAD数据到智能计量:Inspire如何借助HOOPS SDK创计量新高度
  • 【C++11】特殊类的设计 单例模式 类型转换
  • 数据库7(数据定义语句,视图,索引)
  • 单缓冲、双缓冲、多缓冲与缓冲池详解
  • STM32学习之ARM内核自带的中断
  • 【AI论文】SynWorld:用于代理行为知识细化的虚拟场景合成