Redis Search (RediSearch) 高级索引与查询语法

大家好,欢迎来到今天的 Redis Search (RediSearch) 高级索引与查询语法“脱口秀”!我是你们今天的“段子手”兼技术指导。今天咱们不搞虚的,直接上干货,保证让大家听完之后,感觉 Redis Search 不再是“别人家的孩子”,而是你手中一把锋利的“屠龙刀”。

第一幕:索引的艺术 – 超越基础,玩转高级索引

首先,咱们来聊聊索引。别以为索引就是简单的 FT.CREATE 一下,然后就万事大吉了。RediSearch 的索引可是个“百变怪”,可以根据你的需求,变出各种花样。

  • SCHEMA 的进阶之路

    SCHEMA 定义了你的索引结构,决定了哪些字段可以被搜索。 除了基本的 TEXTNUMERICTAG 之外,还有很多高级选项等着你:

    • WEIGHT 加权: 想象一下,你的商品描述里,商品名称的重要性肯定比“颜色”要高吧? WEIGHT 就是用来控制这个的。

      FT.CREATE my_index SCHEMA product_name TEXT WEIGHT 5.0 description TEXT WEIGHT 1.0 color TAG

      这样,搜索 红色 时,商品名称包含“红色”的商品,排名会更靠前。

    • SORTABLE 排序: 有些字段你可能需要用来排序,比如价格、评分等等。 加上 SORTABLE 之后,就可以使用 SORTBY 命令进行排序了。

      FT.CREATE my_index SCHEMA product_name TEXT description TEXT price NUMERIC SORTABLE rating NUMERIC SORTABLE
    • NOINDEX 不索引: 有些字段你可能只需要存储,不需要搜索。 比如用户 ID、创建时间等等。 加上 NOINDEX 可以节省空间,提高性能。

      FT.CREATE my_index SCHEMA product_name TEXT description TEXT user_id NUMERIC NOINDEX created_at NUMERIC NOINDEX
    • WITHSUFFIXTRIE 后缀 Trie 优化: 对于前缀搜索,RediSearch 使用 Trie 结构。 加上 WITHSUFFIXTRIE 可以进一步优化,特别是对于大量相似字符串的场景。

      FT.CREATE my_index SCHEMA product_name TEXT WITHSUFFIXTRIE
    • PHONETIC 语音搜索: 这个就厉害了,可以根据发音来搜索。 比如你输入“苹果”,它能找到“Apple”。 支持多种语言。

      FT.CREATE my_index SCHEMA product_name TEXT PHONETIC dm:en  description TEXT

      这里dm:en代表德语-英语语音编码算法。

    举个例子

    假设我们要创建一个电商商品的索引,包含商品名称、描述、价格、评分、颜色、品牌、以及创建时间。 我们希望商品名称权重高,价格和评分可以排序,颜色和品牌用标签搜索,创建时间不需要索引。

    FT.CREATE product_index SCHEMA 
        product_name TEXT WEIGHT 5.0 
        description TEXT 
        price NUMERIC SORTABLE 
        rating NUMERIC SORTABLE 
        color TAG 
        brand TAG 
        created_at NUMERIC NOINDEX
  • PREFIX 前缀: PREFIX 指定了哪些 key 需要被索引。 默认情况下,RediSearch 会索引所有 key。 但通常我们只会索引特定前缀的 key,比如 product:

    FT.CREATE product_index PREFIX 1 product: SCHEMA ...

    这样,只有以 product: 开头的 key 才会被索引。

  • FILTER 过滤器: FILTER 允许你在索引时过滤数据。 只有满足条件的 key 才会添加到索引。 可以使用 Redis 的表达式语言进行过滤。

    FT.CREATE product_index SCHEMA ... FILTER '@price > 100 && @rating > 4.5'

    只有价格大于 100 且评分大于 4.5 的商品才会被索引。

  • LANGUAGE 语言: 指定索引的语言。 RediSearch 会根据语言进行分词、词干提取等处理。

    FT.CREATE product_index SCHEMA product_name TEXT LANGUAGE chinese description TEXT LANGUAGE english

    这里,商品名称使用中文分词,描述使用英文分词。

第二幕:查询的魔法 – 精准搜索,玩转高级查询语法

索引建好了,接下来就是查询了。 RediSearch 的查询语法非常强大,可以实现各种复杂的搜索需求。

  • 基本语法回顾:

    • *: 匹配所有
    • term: 匹配包含 term 的文档
    • -term: 排除包含 term 的文档
    • |: 或关系
    • (): 优先级
  • 高级查询技巧:

    • @field:value 指定字段查询: 指定在某个字段中搜索。

      FT.SEARCH product_index "@product_name:苹果"

      只在 product_name 字段中搜索 "苹果"。

    • FUZZY {Levenshtein Distance} 模糊搜索: 允许一定的拼写错误。

      FT.SEARCH product_index "%appl%" FUZZY 1

      允许一个字符的拼写错误。

    • PHRASE 短语搜索: 搜索完整的短语。

      FT.SEARCH product_index '"红色 苹果"' PHRASE

      搜索包含 "红色 苹果" 这个完整短语的文档。

    • TAG 标签搜索: 搜索标签字段。

      FT.SEARCH product_index "@color:{红色}"

      搜索 color 字段包含 "红色" 标签的文档。 可以使用 |- 进行标签的或和排除。

    • NUMERIC 数值范围搜索: 搜索数值字段的范围。

      FT.SEARCH product_index "@price:[100 200]"

      搜索 price 字段在 100 到 200 之间的文档。 可以使用 () 表示开区间。

    • GEO 地理位置搜索: 搜索地理位置附近的文档。

      FT.SEARCH geo_index "@location:[-122.4194 37.7749 10 km]"

      搜索 location 字段距离经纬度 (-122.4194, 37.7749) 10 公里范围内的文档。

    • SORTBY 排序: 按照指定字段排序。

      FT.SEARCH product_index "*" SORTBY price DESC

      按照 price 字段降序排序。

    • LIMIT 分页: 限制返回结果的数量。

      FT.SEARCH product_index "*" LIMIT 0 10

      返回第 0 到 9 条记录。

    • RETURN 返回指定字段: 只返回指定的字段。

      FT.SEARCH product_index "*" RETURN 1 product_name 1 price

      只返回 product_nameprice 字段。

    • SUMMARIZE 摘要: 生成文本字段的摘要。

      FT.SEARCH product_index "苹果" SUMMARIZE

      生成包含 "苹果" 的文本字段的摘要。

    • HIGHLIGHT 高亮: 高亮显示搜索关键词。

      FT.SEARCH product_index "苹果" HIGHLIGHT

      高亮显示包含 "苹果" 的关键词。

    • INKEYS 指定 Key 查询: 只在指定的 key 中搜索。

      FT.SEARCH product_index "*" INKEYS 2 product:123 product:456

      只在 product:123product:456 这两个 key 中搜索。

    • INFIELDS 指定字段查询 (多个): 只在指定的多个字段中搜索.

      FT.SEARCH product_index "苹果" INFIELDS 2 product_name description

      只在 product_namedescription 字段中搜索 "苹果"。

    • DIALECT 指定查询语法版本: RediSearch 的查询语法在不断更新,使用 DIALECT 可以指定使用的语法版本。

       FT.SEARCH product_index "*" DIALECT 2
  • 组合查询: 可以将以上技巧组合起来,实现更复杂的搜索需求。

    举个例子

    假设我们要搜索价格在 100 到 200 之间,评分大于 4.5,颜色是红色或蓝色的商品,按照评分降序排序,返回商品名称和价格,高亮显示关键词。

    FT.SEARCH product_index "@price:[100 200] @rating:(4.5 inf] @color:{红色|蓝色}" 
        SORTBY rating DESC 
        RETURN 2 product_name price 
        HIGHLIGHT

第三幕:实战演练 – 电商搜索场景

光说不练假把式,咱们来模拟一个电商搜索场景,把上面学到的东西用起来。

假设我们有以下商品数据:

商品 ID 商品名称 描述 价格 评分 颜色 品牌
1 红色 苹果 新鲜的红富士苹果 120 4.8 红色 苹果
2 蓝色 三星手机 性能强大的三星 Galaxy S23 6999 4.7 蓝色 三星
3 绿色 小米手环 智能健康手环 249 4.6 绿色 小米
4 黑色 华为平板 高清大屏华为 MatePad Pro 3999 4.9 黑色 华为
5 金色 iPhone 14 拍照强大的 iPhone 14 7999 4.5 金色 苹果

首先,创建索引:

FT.CREATE product_index SCHEMA 
    product_name TEXT WEIGHT 5.0 
    description TEXT 
    price NUMERIC SORTABLE 
    rating NUMERIC SORTABLE 
    color TAG 
    brand TAG

然后,将数据添加到 Redis:

HSET product:1 product_name "红色 苹果" description "新鲜的红富士苹果" price 120 rating 4.8 color "红色" brand "苹果"
HSET product:2 product_name "蓝色 三星手机" description "性能强大的三星 Galaxy S23" price 6999 rating 4.7 color "蓝色" brand "三星"
HSET product:3 product_name "绿色 小米手环" description "智能健康手环" price 249 rating 4.6 color "绿色" brand "小米"
HSET product:4 product_name "黑色 华为平板" description "高清大屏华为 MatePad Pro" price 3999 rating 4.9 color "黑色" brand "华为"
HSET product:5 product_name "金色 iPhone 14" description "拍照强大的 iPhone 14" price 7999 rating 4.5 color "金色" brand "苹果"

接下来,进行各种搜索:

  • 搜索包含 "苹果" 的商品:

    FT.SEARCH product_index "苹果"
  • 搜索价格在 100 到 500 之间的商品:

    FT.SEARCH product_index "@price:[100 500]"
  • 搜索颜色是红色或蓝色的商品:

    FT.SEARCH product_index "@color:{红色|蓝色}"
  • 搜索品牌是苹果的商品,按照评分降序排序:

    FT.SEARCH product_index "@brand:{苹果}" SORTBY rating DESC
  • 搜索包含 "手机" 的商品,返回商品名称和描述,高亮显示关键词:

    FT.SEARCH product_index "手机" RETURN 2 product_name description HIGHLIGHT

第四幕:性能优化 – 让搜索飞起来

RediSearch 性能已经很好了,但我们还可以进一步优化。

  • 合理设计 SCHEMA: 只索引需要的字段,避免过度索引。
  • 使用 NOINDEX: 对于不需要搜索的字段,使用 NOINDEX
  • 使用 WITHSUFFIXTRIE: 对于前缀搜索,使用 WITHSUFFIXTRIE
  • 批量索引: 使用 FT.ADDHASHFT.ADD 命令批量添加数据。
  • 使用 Pipeline: 将多个查询命令放入 Pipeline 中执行。
  • 监控性能: 使用 FT.INFO 命令监控索引状态和查询性能。
  • 合理分片: 如果数据量太大,可以考虑将索引分片到多个 Redis 实例上。

表格总结常用查询语法

查询类型 语法 示例 描述
关键词搜索 term FT.SEARCH my_index "apple" 搜索包含 "apple" 的文档
排除关键词 -term FT.SEARCH my_index "-apple" 搜索不包含 "apple" 的文档
或关系 term1 | term2 FT.SEARCH my_index "apple | orange" 搜索包含 "apple" 或 "orange" 的文档
指定字段搜索 @field:value FT.SEARCH my_index "@title:apple" 在 "title" 字段中搜索 "apple"
模糊搜索 %term% FUZZY {Levenshtein Distance} FT.SEARCH my_index "%appl%" FUZZY 1 允许一个字符的拼写错误搜索 "appl"
短语搜索 "{phrase}" PHRASE FT.SEARCH my_index '"red apple" PHRASE' 搜索包含 "red apple" 这个完整短语的文档
标签搜索 @field:{tag1 | tag2} FT.SEARCH my_index "@color:{red|blue}" 搜索 "color" 字段包含 "red" 或 "blue" 标签的文档
数值范围搜索 @field:[min max] FT.SEARCH my_index "@price:[10 100]" 搜索 "price" 字段在 10 到 100 之间的文档
地理位置搜索 @field:[longitude latitude radius unit] FT.SEARCH my_index "@location:[-122.4 37.8 10 km]" 搜索 "location" 字段距离经纬度 (-122.4, 37.8) 10 公里范围内的文档
排序 SORTBY field ASC|DESC FT.SEARCH my_index "*" SORTBY price DESC 按照 "price" 字段降序排序
分页 LIMIT offset num FT.SEARCH my_index "*" LIMIT 0 10 返回第 0 到 9 条记录
返回指定字段 RETURN num field1 field2 ... FT.SEARCH my_index "*" RETURN 1 title 只返回 "title" 字段
摘要 SUMMARIZE FT.SEARCH my_index "apple" SUMMARIZE 生成包含 "apple" 的文本字段的摘要
高亮 HIGHLIGHT FT.SEARCH my_index "apple" HIGHLIGHT 高亮显示包含 "apple" 的关键词
指定Key查询 INKEYS num key1 key2 ... FT.SEARCH my_index "*" INKEYS 2 doc1 doc2 只在 "doc1" 和 "doc2" 这两个 key 中搜索
指定字段查询(多) INFIELDS num field1 field2 ... FT.SEARCH my_index "apple" INFIELDS 2 title content 只在 "title" 和 "content" 字段中搜索 "apple"
指定语法版本 DIALECT version FT.SEARCH my_index "*" DIALECT 2 使用 RediSearch 2.0 查询语法

第五幕:总结与展望 – 星辰大海,未来可期

今天我们一起探索了 RediSearch 的高级索引与查询语法,从 SCHEMA 的进阶之路到各种高级查询技巧,再到实战演练和性能优化,相信大家对 RediSearch 已经有了更深入的了解。

RediSearch 的功能还在不断完善,未来会有更多惊喜等着我们。 比如向量相似度搜索、机器学习集成等等。 让我们一起期待 RediSearch 的未来,也期待大家在实际项目中灵活运用 RediSearch,创造更多价值!

好了,今天的“脱口秀”就到这里。 感谢大家的收听! 如果有什么问题,欢迎随时提问。 我们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注