前言 之前就有考慮過想要研究下RediSearch,號稱高性能全文索引的功能,這幾天閑來無事調研了一番。 RediSearch 介紹 RediSearch 是 Redis Labs 提供的一款強大且高效的搜索和全文索引引擎。它是一個基於 Redis 的模塊,允許用戶在 Redis 資料庫中進行複雜的 ...
前言
之前就有考慮過想要研究下RediSearch,號稱高性能全文索引的功能,這幾天閑來無事調研了一番。
RediSearch 介紹
RediSearch 是 Redis Labs 提供的一款強大且高效的搜索和全文索引引擎。它是一個基於 Redis 的模塊,允許用戶在 Redis 資料庫中進行複雜的搜索和全文檢索操作,而無需將數據導出到其他搜索引擎。
推薦使用場景
RediSearch適合簡單且高效的分詞搜索場景。
針對較為複雜的全文搜索RediSearch肯定是不如ES這種專業的。但假設有一批地址信息,以醫院地址舉例,省市縣地址這些基本欄位,想要快速搜索對應地址一般如下解決方案。
- 使用Like進行模糊匹配:太過雞肋,(比如數據是 【上海市徐匯區宜山路第六人民醫院】,搜索關鍵詞是【上海第六】肯定是搜索不到數據的)。
- ES全文索引: 大材小用,殺雞焉用牛刀
- 自實現分詞和倒排索引,最不推薦!吃力不討好,儘管市面上有很多中文分詞器和全文索引的插件。
這時候就很適合使用RediSearch,既可以實現簡單的(倒排索引)。又不需要使用ES那麼龐大的中間件,集成起來也相對簡單。
RediSearch安裝
RediSearch 官方推薦的 Docker 方式來安裝並啟動。
docker run --name redisearch -p 16379:6379 -v redis-data:/data redis/redis-stack-server:latest
--name redisearch
對容器進行命名-p 16379:6379
宿主機16379映射了容器6379埠-v redis-data:/data
數據捲映射redis/redis-stack-server:latest
表示採用redis-stack-server的最新版本
然後進入容器中查看是否存在對應模塊
docker exec -it redisearch redis-cli
如下圖
RediSearch 創建索引和文檔
創建索引
FT.CREATE hospitalIndex ON HASH PREFIX 1 hospital: LANGUAGE "chinese" SCHEMA id NUMERIC province TEXT SORTABLE city TEXT SORTABLE name TEXT SORTABLE
FT.CREATE hospitalIndex 1.0
表示創建一個名為hospitalIndex的全文索引ON HASH
表示數據結構為HashPREFIX 1 hospital:
表示是Key是以hospital:為首碼的數據LANGUAGE "chinese
指定數據的語言為中文。這對文本分析和分詞很重要,因為針對不同語言有對應的分詞器。SCHEMA id NUMERIC province TEXT SORTABLE city TEXT SORTABLE name TEXT SORTABLE
表示欄位結構是 id,provice city name 其中id為數字類型,其他欄位為文本參與索引
添加索引文檔
ft.add hospitalIndex hospital:1 1.0 language "chinese" fields id 1 province "上海市" city "上海市" name "上海市第六人民醫院"
ft.add hospitalIndex hospital:2 1.0 language "chinese" fields id 2 province "上海市" city "上海市" name "上海交通大學醫學院附屬瑞金醫院"
ft.add hospitalIndex hospital:3 1.0 language "chinese" fields id 3 province "上海市" city "上海市" name "上海交通大學醫學院附屬新華醫院"
ft.add hospitalIndex hospital:4 1.0 language "chinese" fields id 4 province "上海市" city "上海市" name "上海交通大學醫學院附屬上海兒童醫學中心"
ft.add hospitalIndex hospital:5 1.0 language "chinese" fields id 5 province "上海市" city "上海市" name "復旦大學附屬中山醫院"
FT.ADD hospitalIndex hospital:1 1.0:
將一個文檔 hospital:1 添加到 hospitalIndex 索引中,評分為 1.0。LANGUAGE "chinese":
指定文檔的語言為中文。一定要指定對應的語言,這裡會採用中文預設的分詞器。FIELDS:
後面跟著一系列欄位和對應的值。
查詢
ft.search [index] [keywords] language [lang]
從索引名Index中查找對應keywords,而lang為對應語言,預設會按照語言對應的分詞器進行分詞。
示例1
ft.search hospitalIndex "上海市醫院" language "chinese"
示例2
ft.search hospitalIndex "上海市交通大學新華醫院" language "chinese"
示例3
ft.search hospitalIndex "附屬醫院" language "chinese"
不足之處
示例1
儘快已經基本實現了全文索引,但由於RediSearch中的中文分詞器還是有些局限性的。
比如下的幾個搜索:
如上圖所示,上海市第六
是可以搜索到數據的,但 上海第六
就無法搜索到數據了,這是因為RediSearch中的中文分詞器對應拆分不好
示例2
如下圖
上面的幾個搜索例子其實不夠恰當
不過我想強調的主要的目的還是 針對如果分詞中的部分詞性出現了【專業詞】(比如:阿莫西林) 或者類似【第六人】
這種現象,RediSearch沒辦法正確分詞的。 是需要專業的分詞器和自定義字典的
示例3
還有個問題是RediSearch中分詞對應拆詞顆粒度過於細,針對短語的搜索是不夠的,聚合搜索效果很差,因為我這次的演示數據是地址數據所以不好展示處出來。
具體可以參考地址
RediSearch 中預設的中文分詞器可能會根據版本的不一致有差異,一般都是 Friso
當然 RediSearch是支持自定義中文分詞器和自定義字典的,不過那就是另外的話題了,這裡就不提了。
具體可以參考官網:https://redis.io/docs/latest/commands/ft.dictadd/
刪除索引
ft.drop hospitalIndex
RediSearch 總結
角度 | 優勢 | 缺點 |
---|---|---|
場景 | 適合簡單的數據類型和文本 | 不適合複雜的數據類型,比如富文本,長文本 |
集成難度 | 簡單指令, 方便集成 | Redis知識儲備,(這個不算什麼成本吧) |
執行效率 | 基於記憶體,搜索速度很快 | 分詞效果不夠理想,數據量大會影響性能 |
社區生態 | - | 社區目前過於小眾 |
部署 | 簡單搭建,方便集成,支持集群與橫向擴展 | 有一定的不穩定性,畢竟很少見到用於產線環境下。 |
參考地址
- RediSearch/RediSearch
- Redis Real-Time Search, Querying, & Indexing
- RediSearch 高性能的全文搜索引擎
- 關於RediSearch無法正常執行模糊匹配的解決方案