适用于 .NET 的 RedisOM

了解如何使用 Redis Stack 和 .NET 进行构建

Redis OM .NET是一个专门用于处理 Redis Stack 中文档的库。在本教程中,我们将构建一个简单的 ASP.NET Core Web-API 应用程序,用于对简单的 Person & Address 模型执行 CRUD 操作,并且我们将使用 Redis OM .NET 完成所有这些操作。

先决条件

  • .NET 6 SDK
  • 任何用于编写 .NET 的 IDE(Visual Studio、Rider、Visual Studio Code)。
  • RediSearch 必须作为 Redis Stack 配置的一部分进行安装。
  • 可选:Docker Desktop 用于在 docker 中运行 redis-stack 进行本地测试。

跳到代码

如果您想跳过本教程并直接进入代码,所有源代码都可以在GitHub上找到

运行 Redis 堆栈

运行 Redis Stack 有多种方法。一种方法是使用 docker 镜像:

docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack

创建项目

要创建项目,只需运行:

dotnet new webapi -n Redis.OM.Skeleton --no-https --kestrelHttpPort 5000

Redis.OM.Skeleton.csproj然后在您选择的 IDE 中打开该文件。

配置应用程序

在您的文件中添加一个REDIS_CONNECTION_STRING字段appsettings.json来配置应用程序。将该连接字符串设置为 Redis 实例的 URI。如果使用前面提到的 docker 命令,您的连接字符串将是redis://localhost:6379

连接字符串规范

Redis URI 的规范位于此处。对于不包含 的连接字符串,您可以使用:password@host:port或。default:password@host:portusername

创建模型

确保将该Redis.OM包添加到您的项目中。此包可让您轻松创建模型并查询 Redis 域对象。

dotnet add package Redis.OM     

现在是时候创建应用程序用于存储/检索人员的Person/模型了。创建一个名为 的新目录,并将文件和添加到其中。在 中添加以下内容:AddressModelAddress.csPerson.csAddress.cs

using Redis.OM.Modeling;

namespace Redis.OM.Skeleton.Model;

public class Address
{
    [Indexed]
    public int? StreetNumber { get; set; }
    
    [Indexed]
    public string? Unit { get; set; }
    
    [Searchable]
    public string? StreetName { get; set; }
    
    [Indexed]
    public string? City { get; set; }
    
    [Indexed]
    public string? State { get; set; }
    
    [Indexed]
    public string? PostalCode { get; set; }
    
    [Indexed]
    public string? Country { get; set; }
    
    [Indexed]
    public GeoLoc Location { get; set; }
}

在这里,您会注意到,除了StreetName标记为 的之外Searchable,所有字段都用 属性修饰Indexed。这些属性(SearchableIndexed)告诉 Redis OM,您希望能够在查询 Redis Stack 中的文档时使用这些字段。Address本身不是 Document,因此顶级类没有用任何东西修饰;相反,模型Address将嵌入到我们的Person模型中。

为此,将以下内容添加到Person.cs

using Redis.OM.Modeling;

namespace Redis.OM.Skeleton.Model;

[Document(StorageType = StorageType.Json, Prefixes = new []{"Person"})]
public class Person
{    
    [RedisIdField] [Indexed]public string? Id { get; set; }
    
    [Indexed] public string? FirstName { get; set; }

    [Indexed] public string? LastName { get; set; }
    
    [Indexed] public int Age { get; set; }
    
    [Searchable] public string? PersonalStatement { get; set; }
    
    [Indexed] public string[] Skills { get; set; } = Array.Empty<string>();    
    
    [Indexed(CascadeDepth = 1)] public Address? Address { get; set; }
    
}

这里有几点需要注意:

  1. [Document(StorageType = StorageType.Json, Prefixes = new []{"Person"})]指示 Redis OM 用于在 Redis 中存储文档的数据类型为 JSON,并且 Person 类的键的前缀为Person

  2. [Indexed(CascadeDepth = 1)] Address? Address { get; set; }是使用 Redis OM 索引嵌入对象的两种方法之一。此方法指示索引级联到对象图中的对象,CascadeDepth1 表示它将只遍历一个级别,索引对象就像从头开始构建索引一样。另一种方法使用JsonPath您要搜索的各个索引字段的属性。这种更精确的方法限制了索引的大小。

  3. Id属性被标记为RedisIdField。这表示该字段将用于在将文档存储在 Redis 中时生成文档的键名。

创建索引

建立模型后,下一步是在 Redis 中创建索引。管理此问题的最正确方法是将索引创建转移到托管服务中,该服务将在应用程序启动时运行。创建一个HostedServices目录并添加IndexCreationService.cs到该目录中。在该文件中,添加以下内容,这将在启动时创建索引。

using Redis.OM.Skeleton.Model;

namespace Redis.OM.Skeleton.HostedServices;

public class IndexCreationService : IHostedService
{
    private readonly RedisConnectionProvider _provider;
    public IndexCreationService(RedisConnectionProvider provider)
    {
        _provider = provider;
    }
    
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await _provider.Connection.CreateIndexAsync(typeof(Person));
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

接下来,添加以下内容Program.cs以在启动时注册服务:

builder.Services.AddHostedService<IndexCreationService>();

注入 RedisConnectionProvider

Redis OM 使用该类RedisConnectionProvider来处理与 Redis 的连接,并提供可用于与 Redis 交互的类。要使用它,只需将 RedisConnectionProvider 的实例注入到您的应用中。在您的Program.cs文件中,添加:

builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration["REDIS_CONNECTION_STRING"]));

这会从配置中拉出连接字符串并初始化提供程序。现在,该提供程序将可在您的控制器/服务中使用。

创建 PeopleController

最后一个难题是为我们的 People API 编写实际的 API 控制器。在controllers目录中,添加文件PeopleController.cs,类的骨架PeopleController将是:

using Microsoft.AspNetCore.Mvc;
using Redis.OM.Searching;
using Redis.OM.Skeleton.Model;

namespace Redis.OM.Skeleton.Controllers;

[ApiController]
[Route("[controller]")]
public class PeopleController : ControllerBase
{

}

注入 RedisConnectionProvider

要与 Redis 交互,请注入 RedisConnectionProvider。在此依赖项注入期间,拉出一个RedisCollection<Person>实例,这将允许在 Redis 中查询文档的流畅界面。

private readonly RedisCollection<Person> _people;
private readonly RedisConnectionProvider _provider;
public PeopleController(RedisConnectionProvider provider)
{
    _provider = provider;
    _people = (RedisCollection<Person>)provider.RedisCollection<Person>();
}

添加创建人员的路线

添加到 API 的第一条路线是使用 创建人员的 POST 请求,RedisCollection它就像调用InsertAsync并传入人员对象一样简单:

[HttpPost]
public async Task<Person> AddPerson([FromBody] Person person)
{
    await _people.InsertAsync(person);
    return person;
}

添加按年龄过滤的路线

添加到 API 的第一个过滤路由将允许用户按最小和最大年龄进行过滤。使用 提供的 LINQ 接口RedisCollection,这是一个简单的操作:

[HttpGet("filterAge")]
public IList<Person> FilterByAge([FromQuery] int minAge, [FromQuery] int maxAge)
{        
    return _people.Where(x => x.Age >= minAge && x.Age <= maxAge).ToList();
}

按地理位置过滤

Redis OM 具有一个GeoLoc数据结构,其实例由Address模型索引,使用该方法以及要过滤的字段,RedisCollection可以找到具有特定位置半径的所有对象:GeoFilter

[HttpGet("filterGeo")]
public IList<Person> FilterByGeo([FromQuery] double lon, [FromQuery] double lat, [FromQuery] double radius, [FromQuery] string unit)
{
    return _people.GeoFilter(x => x.Address!.Location, lon, lat, radius, Enum.Parse<GeoLocDistanceUnit>(unit)).ToList();
}

按精确字符串过滤

当模型中的字符串属性标记为 时Indexed,例如FirstNameLastName,Redis OM 可以对它们执行精确的文本匹配。例如,以下两个路由 filter byPostalCode和 name 演示了精确的字符串匹配。

[HttpGet("filterName")]
public IList<Person> FilterByName([FromQuery] string firstName, [FromQuery] string lastName)
{
    return _people.Where(x => x.FirstName == firstName && x.LastName == lastName).ToList();
}

[HttpGet("postalCode")]
public IList<Person> FilterByPostalCode([FromQuery] string postalCode)
{
    return _people.Where(x => x.Address!.PostalCode == postalCode).ToList();
}

当模型中的属性被标记为Searchable、如StreetAddress和 时PersonalStatement,您可以执行全文搜索,查看 和 的过滤PersonalStatementStreetAddress

[HttpGet("fullText")]
public IList<Person> FilterByPersonalStatement([FromQuery] string text){
    return _people.Where(x => x.PersonalStatement == text).ToList();
}

[HttpGet("streetName")]
public IList<Person> FilterByStreetName([FromQuery] string streetName)
{
    return _people.Where(x => x.Address!.StreetName == streetName).ToList();
}

按数组成员身份过滤

当字符串数组或列表标记为 时Indexed,Redis OM 可以使用数组或列表的方法筛选出包含给定字符串的所有记录Contains。例如,我们的Person模型有一个技能列表,您可以通过添加以下路由来查询。

[HttpGet("skill")]
public IList<Person> FilterBySkill([FromQuery] string skill)
{
    return _people.Where(x => x.Skills.Contains(skill)).ToList();
}

更新人员

使用 Redis OM 更新 Redis Stack 中的文档可以通过首先具体化 person 对象、进行所需的更改,然后调用Save集合来完成。集合负责跟踪对其中具体化的实体所做的更新;因此,它将跟踪并应用您在其中所做的任何更新。例如,添加以下路由以根据其 ID 更新 Person 的年龄:

[HttpPatch("updateAge/{id}")]
public IActionResult UpdateAge([FromRoute] string id, [FromBody] int newAge)
{
    foreach (var person in _people.Where(x => x.Id == id))
    {
        person.Age = newAge;
    }
    _people.Save();
    return Accepted();
}

删除一个人

可以使用 来从 Redis 中删除文档Unlink。只需调用 Unlink 并传入键名即可。给定一个 id,我们可以使用前缀和 id 重建键名:

[HttpDelete("{id}")]
public IActionResult DeletePerson([FromRoute] string id)
{
    _provider.Connection.Unlink($"Person:{id}");
    return NoContent();
}

运行应用

现在剩下要做的就是运行应用程序并对其进行测试。您可以通过运行来执行此操作dotnet run,该应用程序现在在端口 5000 上公开,并且应该有一个 swagger UI,您可以使用它在 http://localhost:5000/swagger 上使用 API。有几个脚本以及一些数据文件,可以使用GitHub 存储库中的 API 将一些人插入 Redis

使用 Redis Insight 查看数据

您可以安装 Redis Insight GUI 或使用在 http://localhost:8001/ 上运行的 Redis Insight GUI。

您可以按照以下步骤查看数据:

  1. 接受 EULA

接受 EULA

  1. 单击添加 Redis 数据库按钮

添加 Redis 数据库按钮

  1. 输入 redis 服务器的主机名和端口名。如果您使用的是 docker 镜像,则为该名称,localhost6379为数据库指定一个别名

配置 Redis Insight 数据库

  1. 点击Add Redis Database.

资源

本教程的源代码可以在GitHub中找到。

给此页面评分
返回顶部 ↑