共计 4096 个字符,预计需要花费 11 分钟才能阅读完成。
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),备注来意,邀请进群
—— END ——
作者简介
马跃:MASA 技术团队成员。