视频

了解更多
嵌入式文档、索引数组以及 Redis OM .NET 的其他令人惊叹的补充!
2021 年 11 月,我们发布了 Redis OM .NET(用于 Redis 的对象映射库)的 v0.1.0 版本。当然,与任何早期发布的软件一样,还有更多工作要做。从那时起,我们解决了一些库的怪癖。我们还为 .NET 添加了一些激动人心的新功能,以便开发人员能够快速提高生产力。
在查看新增功能之前,如果您需要 Redis OM 的总体概述,可以查看 公告帖子 或观看下面的视频。
现在,让我们来看看为 Redis OM .NET 添加的新功能!
Redis OM .NET 现在允许您索引模型中嵌入对象中的字段。例如,假设您有一个 Customer 模型,其中包含一个嵌入式 Address 模型。
[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; }
}
您可以像这样从您的 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; }
[Indexed(CascadeDepth=1)]
public Address Address {get; set;}
}
CascadeDepth 指的是您想要索引的对象图的深度。设置级联深度将导致 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 以前仅支持数字、字符串和 GeoLoc 的索引。自 0.2.0 版本起,您还可以索引枚举、ULID、GUID 和布尔值。为此,请使用 IndexedAttribute 来修饰模型中的这些字段。
对于聚合用户的痛点之一是,并非所有字段都可以或一定标记为可聚合的。因此,这些字段以前在 Redis OM 中无法用于聚合。使用 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();
加载模型中的多个字段,请注意匿名类型。
聚合的另一个怪癖是它们不返回格式良好的对象。造成这种情况的原因是,聚合会返回其管道的结果,这通常正是其完成所有请求的操作所需的结果及其操作的结果。现在这个问题已经解决了。
使用新的水合 API,您可以将这些片段整理成更易用的格式,使您能够从 RedisAggreagtionResult 中完全或部分水合您的模型。
让我们回顾一下 Load 部分中的示例。如果我们想将整个 customer 模型以及 apply 函数的结果带回来,该怎么办?我们可以通过调用 LoadAll 而不是 Load 来实现。然后,当枚举每个 RedisAggregationResult 时,我们调用其上的 Hydrate。Hydrate 尝试将 AggregationResult 中的任何内容绑定到您的模型。因此,可能存在 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 上创建一个问题。