Redis OM
Redis OM 是 Redis 官方推出的對象映射框架,即:Object Mapping。讓開發人員更簡單、方便的操作 Redis 數據。Redis 存儲的數據抽象為對象映射,支持基於對象的 Redis 數據持久化、流式查詢操作。
目前只支持 4 種開發語言:
- Redis OM for Spring
- Redis OM for .NET
- Redis OM for Node.js
- Redis OM for Python
Redis OM .NET
Redis OM .NET 是.Net 平台的 Redis OM,依賴 StackExchange.Redis 實現。借助 Redis OM .NET 可以實現對象操作的方式操作 Redis 數據,脫離 key/value 的操作方式。
查詢支持大部分.Neter 最愛的 LINQ。
快速開始
安裝對應包
dotnet add package Redis.OM
Redis 環境准備
直接使用 Docker 的方式安裝 Redis 環境。
docker run -p 6379:6379 redislabs/redismod:preview
標准的官方鏡像是無法支持 Redis OM,需要 Redis Modules 支持,Redis OM 核心創建索引、查詢數據依賴
RediSearch
這個 Module 實現。依賴的 Module 有:RediSearch、RedisJSON。
RedisJSON 的依賴不是必須的,但是會缺少相應的功能,如:模型嵌套、復雜查詢(只支持 key 查詢)
Coding
增加抽象對象定義
[Document]
public class Customer
{
[RedisIdField]
public string Id { get; set; }
[Indexed(Sortable = true, Aggregatable = true)]
public string FirstName { get; set; }
[Indexed(Sortable = true, Aggregatable = true)]
public string LastName { get; set; }
[Indexed]
public string Email { get; set; }
[Indexed(Sortable = true)]
public int Age { get; set; }
}
Document、Indexed、Searchable 等特性介紹,介紹參考 Github -> document-attribute
獲取抽象對象的操作集合、創建索引
var provider = new RedisConnectionProvider("redis://localhost:6377");
var connection = provider.Connection;
var customers = provider.RedisCollection<Customer>();
connection.CreateIndex(typeof(Customer));
查詢數據、聚合操作等需要依據索引,所以一定要先調用connection.CreateIndex
創建索引,對應 RediSearch 的FT.CREATE
命令。
connection.CreateIndex(typeof(Customer)) 創建索引重復執行會拋出異常
Index already exists
。雖然可以通過connection.Execute("FT.INFO", $"customer-idx")
獲取索引信息,但是第一次索引不存在時會拋出Unknown Index name
。所以實際使用中可能需要一個 try-catch 包住CreateIndex
方法避免異常。
插入數據
var id = customers.Insert(new Customer { FirstName = "Steve", Email = "xxxx@masa.com", Age = 1 });
var id2 = customers.Insert(new Customer { FirstName = "FirstName", LastName = "LastName", Email = "xxxx@masa.com" });
id,id2 為插入數據的 key,沒有指定 Document 的 Prefixes 和 IdGenerationStrategy,則默認為 ULID 格式為{DocumentName}:{Ulid}
,如:`Cust
插入數據時需要注意的是,如果對沒有明確指定字段的值,如 LastName 不明確賦值:
customers.Insert(new Customer { FirstName = "Steve", Email = "xxxx@masa.com", Age = 1 });
,查看 Redis 中存的數據可以發現當前 key 存儲的 json 數據沒有未指定的字段對應的 key(此時 Query 或 Aggregations 會有些奇怪的錯誤)。可以根據自己需要,顯示的為字段賦個零值或者在定義實體時使用public string LastName { get; set; } = string.Empty;
的方式。
查詢數據
var customer = customers.Where(x => x.Age == 0).OrderBy(a => a.FirstName).FirstOrDefault();
var customerById = customers.FindById(id);//根據Id查找
var emails = customers.Select(x => x.Email);//僅查詢指定字段
var takes = customers.Where(x => x.Age > 0).Take(10);//獲取指定條數
var adults = customers.Where(x => x.Age >= 0).Skip(5);//查詢偏移
對於空值的判斷,x.FirstName == ""【語法錯誤】 或 string.IsNullOrEmpty(x.FirstName)【不支持】。Redis 哈希中不能有空字符串,所以類似的查詢應該通過聚合操作的Exists
方法實現
foreach (var agg in customerAggregations.Apply(x => ApplyFunctions.Exists(x.RecordShell.LastName), "LastNameExists"))
{
Console.WriteLine($"{agg["LastNameExists"]}");
}
聚合操作
流水線(Pipelining)同時發送多個請求,從而減輕延遲。結果的查詢和轉化都在 Redis 端完成。
RecordShell 是遠端 Index 類型的結構,RecordShell 應該只在聚合操作流水線內部使用,運行時並沒有真正的值。
拼湊 FirstName 和 LastName,返回 FullName
var customerAggregations = provider.AggregationSet<Customer>();
var age = customerAggregations.Average(x => x.RecordShell.Age);
var sets = customerAggregations.Where(a => a.RecordShell.FirstName == "Steve").Apply(x => string.Format("{0} {1}", x.RecordShell.FirstName, x.RecordShell.LastName), "FullName");
foreach (var item in sets)
{
Console.WriteLine(item["FullName"].ToString());
}
聚合分組
通過 GroupBy 方法,依據不同屬性進行分組聚合(支持單字段分組和多字段分組)。
var res = customerAggregations
.GroupBy(x => x.RecordShell.FirstName)
.GroupBy(x => x.RecordShell.LastName)
.ToArray();
var res1 = customerAggregations.GroupBy(x => x.RecordShell.FirstName).CloseGroup().ToArray();
CloseGroup 可以關閉分組,轉換為正常的聚合操作,即 GroupedAggregationSet 到 RedisAggregationSet 的一個轉換。
public static RedisAggregationSet<T> CloseGroup<T>(this GroupedAggregationSet<T> source)
{
return new RedisAggregationSet<T>(source, source.Expression);
}
結尾
本文只是對 Redis OM .NET 用法的簡單梳理和可用性驗證。
更多用法以及用法更新參考Github
我們正在行動,新的框架、新的生態
我們的目標是自由的
、易用的
、可塑性強的
、功能豐富的
、健壯的
。
所以我們借鑒Building blocks的設計理念,正在做一個新的框架MASA Framework
,它有哪些特點呢?
- 原生支持Dapr,且允許將Dapr替換成傳統通信方式
- 架構不限,單體應用、SOA、微服務都支持
- 支持.Net原生框架,降低學習負擔,除特定領域必須引入的概念,堅持不造新輪子
- 豐富的生態支持,除了框架以外還有組件庫、權限中心、配置中心、故障排查中心、報警中心等一系列產品
- 核心代碼庫的單元測試覆蓋率90%+
- 開源、免費、社區驅動
- 還有什么?我們在等你,一起來討論
經過幾個月的生產項目實踐,已完成POC,目前正在把之前的積累重構到新的開源項目中
目前源碼已開始同步到Github(文檔站點在規划中,會慢慢完善起來):
QQ群:7424099
微信群:加技術運營微信(MasaStackTechOps),備注來意,邀請進群
------ END ------
作者簡介
馬躍:MASA技術團隊成員。