Redis OM .NET Redis對象映射框架


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(文檔站點在規划中,會慢慢完善起來):

MASA.BuildingBlocks

MASA.Contrib

MASA.Utils

MASA.EShop

BlazorComponent

MASA.Blazor

QQ群:7424099

微信群:加技術運營微信(MasaStackTechOps),備注來意,邀請進群

masa_stack_tech_ops.png

​ ------ END ------

作者簡介

馬躍:MASA技術團隊成員。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM