视频

了解更多
嵌入式文档、索引数组以及 Redis OM .NET 的其他强大新增功能!
2021 年 11 月,我们发布了 Redis OM .NET(Redis 的对象映射库)的 v0.1.0 版本。 当然,与任何早期版本软件一样,还有很多工作要做。 从那时起,我们解决了该库的一些怪癖。 我们还在 .NET 中添加了几个令人兴奋的新功能,以使开发人员能够快速提高生产力。
在查看新内容之前,如果您需要 Redis OM 的一般概述,可以查看公告帖子或观看下面的视频。
现在,让我们看看添加到 Redis OM .NET 的新功能!
Redis OM .NET 现在允许您索引模型中嵌入式对象中的字段。 例如,假设您有一个带有嵌入式 Address 模型的 Customer 模型
[Document(StorageType = StorageType.Json)]
public class Customer
{
[Indexed] public string FirstName { get; set; }
[Indexed] public string LastName { get; set; }
public string Email { get; set; }
public Address Address {get; set;}
}
public class Address
{
public string StreetName { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public string State { get; set; }
public GeoLoc Location { get; set; }
public int HouseNumber { get; set; }
}
以前,您将无法索引 Customer 中的嵌入式 Address。 现在,Redis OM .NET 提供了两种方法来执行此操作。
假设您想在其他模型之间共享嵌入式模型,并且不想过度索引嵌入式模型中的字段。
您可以将嵌入式模型单独保留,并使用相对于模型根目录的 JSON 路径从您的模型中对其进行索引。 要索引 Customer 的 Address 中的 City 和 State
[Document(StorageType = StorageType.Json)]
public class Customer
{
[Indexed] public string FirstName { get; set; }
[Indexed] public string LastName { get; set; }
public string Email { get; set; }
[Indexed(JsonPath = "$.City")]
[Indexed(JsonPath = "$.State")]
public Address Address {get; set;}
}
完成此操作的另一种方法是声明要在 Address 类中索引的内容,并使用 IndexedAttribute 的“CascadeDepth”属性级联到其中。 所以使用以下 Address 模型
[Document(StorageType = StorageType.Json)]
public class Address
{
public string StreetName { get; set; }
public string ZipCode { get; set; }
[Indexed] public string City { get; set; }
[Indexed] public string State { get; set; }
[Indexed] public GeoLoc Location { get; set; }
[Indexed] public int HouseNumber { get; set; }
}
您可以像这样从您的客户模型中索引
[Document(StorageType = StorageType.Json)]
public class Customer
{
[Indexed] public string FirstName { get; set; }
[Indexed] public string LastName { get; set; }
public string Email { get; set; }
[Indexed(CascadeDepth=1)]
public Address Address {get; set;}
}
CascadeDepth 指的是您要索引到对象图中的深度。 设置 Cascade 深度将导致 Redis OM 遵循所有 IndexedAttribute 和 SearchableAttribute 来查找要在模型对象图中索引的字段。
使用这两种模式之一,当您创建索引时,嵌入式文档将按您期望的方式进行索引,然后当您运行像这样的 LINQ 查询时
customers.Where(c=>c.Address.ZipCode == "10001");
… Redis OM 知道如何根据提供的模型正确构建查询。
自 v0.1.0 以来,我们添加到 Redis OM 的另一个很棒的功能是能够索引和查询 JSON 对象中的字符串数组。 使用 IndexedAttribute.装饰数组。
[Document(StorageType = StorageType.Json, Prefixes = new []{"Person"})]
public class Person
{
[RedisIdField] [Indexed]public string? Id { get; set; }
[Indexed] public string[] Skills { get; set; } = Array.Empty<string>();
[Indexed] public string? FirstName { get; set; }
[Indexed] public string? LastName { get; set; }
}
完成此操作后,您可以使用数组的 Contains 方法查询这些数组
people.Where(x => x.Skills.Contains(skill));
Redis OM 之前仅支持索引数值、字符串和 GeoLocs。 从 0.2.0 版本开始,您还可以索引枚举、ULID、GUID 和布尔值。 为此,请使用 IndexedAttribute 来装饰模型中的这些字段。
对于聚合用户来说,一个痛点是并非所有字段都可以标记为或必须标记为可聚合。 因此,这些字段以前没有资格在 Redis OM .NET 中的聚合中使用。 借助 Redis OM 中 AggregationSet 中的新 Load 和 LoadAll 方法,现在可以加载未标记为可聚合的字段。
让我们采用我们之前使用的 Customer 模型并添加一个 age 字段来演示它的工作原理。
public class Customer
{
[Indexed] public string FirstName { get; set; }
[Indexed] public string LastName { get; set; }
[Indexed] public int Age { get; set; }
public string Email { get; set; }
[Indexed(JsonPath = "$.City")]
[Indexed(JsonPath = "$.State")]
public Address Address {get; set;}
}
Age 已索引,但未标记为可聚合。 以前,我们无法在聚合管道中使用 Age。 如果我们运行类似这样的代码,我们会收到错误,因为 Age 没有加载到管道中
var aggregations = provider.AggregationSet<Customer>();
await aggregations.Apply(c=>c.RecordShell.Age + 5, "Age_plus_five")
.ToArrayAsync();
现在,在 Redis OM .NET 中,您可以在 AggregationSet 上调用 Load,加载单个字段或多个字段(通过初始化一个匿名对象)
await aggregations.Load(x=>x.RecordShell.Age)
.Apply(c=>c.RecordShell.Age + 5, "Age_plus_five")
.ToArrayAsync();
仅加载 Age 或
await aggregations.LoadAll
.Apply(c=>c.RecordShell.Age + 5, "Age_plus_five")
.Apply(c=>string.Format("My Name is {0}",c.RecordShell.FirstName), "myNameIs")
.ToArrayAsync();
要从模型中加载多个字段,请注意匿名类型。
聚合的另一个怪癖是它们不会返回格式良好的对象。 原因是聚合返回其管道的结果,这通常正是完成所请求的所有操作及其操作结果所需要的。 现在已经修复了。
借助新的 Hydration API,您可以将这些位拼凑成更可用的格式,从而允许您从 RedisAggreagtionResult 中完全或部分水合您的模型。
让我们回顾一下 Load 部分的示例。 如果我们想将整个客户模型以及 apply 函数的结果带回来怎么办? 我们可以通过调用 LoadAll 而不是 Load 来做到这一点。 然后,我们在枚举每个 RedisAggregationResult 时调用 Hydrate。 Hydrate 尝试将 AggregationResult 中的任何内容绑定到您的模型。 因此,可能存在结果中不存在的空字段。
var collection = new RedisAggregationSet<Person>(_connection);
await foreach (var result in aggregations.LoadAll
.Apply(c=>c.RecordShell.Age + 5, "Age_plus_five")
.Apply(c=>string.Format("My Name is {0}",c.RecordShell.FirstName), "myNameIs"))
{
var person = result.Hydrate(); //now a fully hydrated Person object!
}
在 Redis OM 的先前迭代中,如果您想更新某个项目,则需要枚举它、更新它,然后保存整个 RedisCollection。 这可能很麻烦。 我们添加了一个新的 API,使您可以轻松地更新存储在 Redis 中的对象。
await collection.UpdateAsync(object);
同样,我们简化了删除插入到 Redis 中的对象的操作。 要删除对象,请执行
await customers.DeleteAsync(object);
一个被请求的功能是传递 ConnectionMultiplexer 以初始化 RedisConnectionProvider。 此构造函数允许您将您已经注入到 Redis OM 的其他服务中的任何复用器一起使用。
Redis OM 现在支持可配置的块大小,用于在底层进行自动分页。 以前,固定的块大小可能会对巨大的查询结果产生性能影响。 较小且不可配置的块大小,加上较大的结果集,可能会导致 Redis OM 必须进行多次往返才能具体化整个结果集。 现在,您可以将所需的块大小传递给 Redis OM。
var customers = provider.RedisCollection<Customer>(10000);
请注意,这受 RediSearch 中的 MAXSEARCHRESULT 配置参数的限制。
在过去的几个月中,我们做了很多工作,为 Redis OM .NET 添加了许多令人兴奋的新功能,以及任何软件都不可避免的错误修复。 您可以通过关注 GitHub 存储库 来关注新功能。 如果您有兴趣在库中看到某些功能,请在 GitHub 上打开一个问题。