天天看點

C#+Redis Search:如何用Redis實作高性能全文搜尋

作者:opendotnet

Redis Search是一個Redis子產品,它使用壓縮的反向索引來實作快速的索引和低記憶體占用。Redis Search可以對Redis資料進行精确短語比對、模糊搜尋、數值過濾、地理空間篩選等多種搜尋功能。Redis Search還支援聚合、高亮、詞幹提取、拼寫糾錯等特性。

//Redis Search文檔位址              https://redis.io/docs/interact/search-and-query/           

RediSearch查詢語言類似于SQL,但更加簡潔和靈活。你可以使用RediSearch指令來建立索引、添加文檔、搜尋文檔、更新文檔、删除文檔等。

與elasticsearch的比較

elasticsearch是另一個流行的開源搜尋引擎,它也支援全文搜尋和聚合功能。那麼,Redis Search和elasticsearch有什麼差別和優勢呢?

  • Redis Search是基于記憶體的,它可以提供更高的性能和更低的延遲。elasticsearch則是基于磁盤的,它需要依賴緩存來提高速度。
  • Redis Search是一個Redis子產品,它可以直接在Redis中運作,無需額外的安裝和配置。elasticsearch則需要單獨部署和管理。
  • Redis Search支援多種擴充子產品,如RedisJSON(用于處理JSON文檔),RedisGraph(用于處理圖資料),RedisTimeSeries(用于處理時間序列資料),RediSearch(用于處理全文搜尋)等。elasticsearch則需要依賴插件來擴充其功能。

一、Redis Search的安裝

有多種方式可以安裝和使用Redis Search,最簡單的方式是使用Redis Stack Docker鏡像,它已經內建了Redis和多個子產品,包括Redis Search。隻需運作一條指令,就可以在本地建立一個RediSearch容器:

$ docker run -p 6379:6379 redis/redis-stack-server:latest           

要連接配接到這個執行個體,運作:

$ redis-cli           

二、Redis Search的使用

要使用Redis Search,你首先需要在Redis資料上聲明索引,然後使用RediSearch查詢語言來查詢這些資料。

1、建立索引

要建立一個索引,你需要使用FT.CREATE指令,并指定索引名、索引選項和字段名。例如,要建立一個名為blog的索引,用于存儲部落格文章的标題、内容和标簽,你可以運作:

127.0.0.1:6379> FT.CREATE blog ON HASH PREFIX 1 blog: SCHEMA title TEXT WEIGHT 5.0 content TEXT WEIGHT 1.0 tags TAG SEPARATOR ","              OK           

這個指令會建立一個名為blog的索引,它會自動索引所有以blog:為字首的散列鍵。它還會指定三個字段:title(文本類型,權重為5.0),content(文本類型,權重為1.0)和tags(标簽類型,分隔符為逗号)。

2、添加文檔

要添加一個文檔到索引中,你需要使用FT.ADD指令,并指定文檔ID、字段值和分數。例如,要添加一篇部落格文章到blog索引中,你可以運作:

127.0.0.1:6379> FT.ADD blog blog:1 1.0 FIELDS title "Hello Redis Search" content "This is a blog post about Redis Search, a query and full-text search engine for Redis." tags "redis,search"              OK           

這個指令會添加一個ID為blog:1的文檔到blog索引中,并給它一個分數為1.0(預設為1.0)。它還會指定三個字段的值:title為"Hello Redis Search",content為"This is a blog post about Redis Search, a query and full-text search engine for Redis.“,tags為"redis,search”。

3、搜尋文檔

要搜尋一個文檔,你需要使用FT.SEARCH指令,并指定索引名和查詢表達式。你可以使用多種查詢文法,如精确比對、模糊比對、數值過濾、布爾運算等。例如,要搜尋blog索引中包含"redis"或"search"的文檔,你可以運作:

127.0.0.1:6379> FT.SEARCH blog "redis|search"              1) (integer) 1              2) "blog:1"              3) 1) "title"              2) "Hello Redis Search"              3) "content"              4) "This is a blog post about Redis Search, a query and full-text search engine for Redis."              5) "tags"              6) "redis,search"               

這個指令會傳回一個結果集,包含比對的文檔數量、文檔ID和字段值。你可以使用LIMIT選項來分頁查詢,或者使用RETURN選項來指定傳回哪些字段。

4、更新文檔

要更新一個文檔,你需要使用FT.PARTIAL指令,并指定文檔ID和要更新的字段值。例如,要更新blog:1文檔的标題和标簽,你可以運作:

127.0.0.1:6379> FT.PARTIAL blog blog:1 REPLACE FIELDS title "Hello RediSearch" tags "redis,search,full-text"              OK           

這個指令會更新blog:1文檔的title和tags字段的值,并重新索引這些字段。

5、删除文檔

要删除一個文檔,你需要使用FT.DEL指令,并指定文檔ID。例如,要删除blog:1文檔,你可以運作:

127.0.0.1:6379> FT.DEL blog blog:1              (integer) 1           

這個指令會從索引和資料庫中删除blog:1文檔,并傳回删除的數量。

三、C#操作Redis Search結構

這裡使用了NRediSearch和StackExchange.Redis兩個庫,實作在C#中使用Redis和RediSearch的功能。也可以把NRediSearch換為NRedisStack庫,NRedisStack庫基于 StackExchange.Redis 建構,旨在為 C# 生态系統提供對 Redis Stack 指令的原生支援。

//項目位址:              //NRedisStack              https://github.com/redis/NRedisStack              //NRediSearch              https://github.com/StackExchange/NRediSearch              //StackExchange.Redis              https://github.com/StackExchange/StackExchange.Redis           

以下demo中已添加詳細注釋,是基于本文中有關Redis Search使用樣例的C#實作,大家可對比閱讀。

// 引入NRediSearch和StackExchange.Redis命名空間              using NRediSearch;              using StackExchange.Redis;                  public class RediSearchDemoProgram              {              private static void Main(string[] args)              {              // 建立一個連接配接到本地Redis執行個體的連接配接器              ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");              // 擷取一個資料庫對象              IDatabase db = redis.GetDatabase();                  // 建立一個名為blog的索引,用于存儲部落格文章的标題、内容和标簽              var client = new Client("blog", db); // 建立一個用戶端對象              client.CreateIndex(new Schema() // 建立一個索引對象              .AddTextField("title", 5.0) // 文本類型,權重為5.0              .AddTextField("content", 1.0) // 文本類型,權重為1.0              .AddTagField("tags", ","), new Client.ConfiguredIndexOptions()); // 标簽類型,分隔符為逗号                  // 添加一篇部落格文章到blog索引中              client.AddDocument(              // 添加一個文檔對象              new Document("blog:1", new Dictionary<string, RedisValue> {              { "title", "Hello Redis Search"},//設定标題字段              { "content", "This is a blog post about Redis Search, a query and full-text search engine for Redis."}, // 設定内容字段              { "tags", "redis,search"}, // 設定标簽字段              }));                  // 搜尋blog索引中包含"redis"或"search"的文檔              var result = client.Search(new Query("redis|search")); // 建立一個查詢對象              Console.WriteLine(result.TotalResults); // 列印比對的文檔數量              foreach (var doc in result.Documents)              {              Console.WriteLine(doc.Id); // 列印文檔ID              Console.WriteLine(doc["title"]); // 列印标題字段              Console.WriteLine(doc["content"]); // 列印内容字段              Console.WriteLine(doc["tags"]); // 列印标簽字段              }                  // 更新blog:1文檔的标題和标簽              client.UpdateDocument("blog:1", new Dictionary<string, RedisValue> {              { "title", "Hello RediSearch"},//更新标題字段              { "tags", "redis,search,full-text"}, // 更新标簽字段              });                  // 删除blog:1文檔              client.DeleteDocument("blog:1");              }              }           

本文就到這裡了,下一篇我們來探索如何通過Redis Search進行基于向量的搜尋,實作文本相似度查詢。相比之下,這種搜尋方式可以保留文本中的語義、文法和情感資訊。

繼續閱讀