写点什么

Redis OM .NET Redis 对象映射框架

  • 2022 年 1 月 21 日
  • 本文字数:2862 字

    阅读完需:约 9 分钟

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

发布于: 刚刚阅读数: 2
用户头像

还未添加个人签名 2021.10.26 加入

还未添加个人简介

评论

发布
暂无评论
Redis OM .NET Redis对象映射框架