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技术团队成员。