关于后端:Redis-OM-NET-Redis对象映射框架

44次阅读

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

正文完
 0