前言
之前就有考慮過想要研究下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無法正常執行模糊匹配的解決方案
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無法正常執行模糊匹配的解決方案