学习

RedisCollection 提供了一个用于查询存储在 redis 中的对象的流畅接口。这意味着如果您使用 Redis OM 库将对象存储在 Redis 中,并且您正在运行 Redis Stack,则可以使用您熟悉的 LINQ 语法轻松地查询存储在 Redis 中的对象。

定义模型#

让我们从定义一个我们将用于查询的模型开始,我们将使用一个 Employee 类,其中将包含我们可能想要查询的一些基本内容

[Document]
public class Employee
{
    [Indexed]
    public string Name { get; set; }

    [Indexed(Aggregatable = true)]
    public int Age { get; set; }

    [Indexed(Aggregatable = true)]
    public double Sales { get; set; }

    [Searchable(Aggregatable = true)]
    public string Department { get; set; }
}

连接到 Redis#

现在我们将初始化一个 RedisConnectionProvider,并获取 Employee 的 RedisCollection 的句柄

static async Task Main(string[] args)
{
    var provider = new RedisConnectionProvider("redis://localhost:6379");
    var connection = provider.Connection;
    var employees = prover.RedisCollection<Employee>();
    await connection.CreateIndexAsync(typeof(Employee));
}

创建我们的索引#

接下来我们将创建索引,所以接下来在我们的 Main 方法中,让我们将我们的类型压缩成一个索引

播种一些数据#

接下来,我们将对数据库中的几个数据片段进行播种,以便进行尝试

var e1 = new Employee {Name = "Bob", Age = 35, Sales = 100000, Department = "EMEA Sales"};
var e2 = new Employee {Name = "Alice", Age = 52, Sales = 300000, Department = "Partner Sales"};
var e3 = new Employee {Name = "Marcus", Age = 42, Sales = 250000, Department = "NA Sales"};
var e4 = new Employee {Name = "Susan", Age = 27, Sales = 200000, Department = "EMEA Sales"};
var e5 = new Employee {Name = "John", Age = 38, Sales = 275000, Department = "APAC Sales"};
var e6 = new Employee {Name = "Theresa", Age = 30, Department = "EMEA Ops"};
var insertTasks = new []
    {
        employees.InsertAsync(e1),
        employees.InsertAsync(e2),
        employees.InsertAsync(e3),
        employees.InsertAsync(e4),
        employees.InsertAsync(e5)
        employees.InsertAsync(e6)
    };
await Task.WhenAll(insertTasks);

已索引字段的简单文本查询#

将这些数据插入我们的数据库后,我们现在可以开始查询了。让我们从尝试按名称查询人员开始。我们可以使用简单的 Where 谓词搜索所有名为 Susan 的员工

var susans = employees.Where(x => x.Name == "Susan");
await foreach (var susan in susans)
{
    Console.WriteLine($"Susan is {susan.Age} years old and works in the {susan.Department} department ");
}

Where 谓词还支持 and/or 运算符,例如,要查找所有名为 AliceBob 的员工,您可以使用

var AliceOrBobs = employees.Where(x => x.Name == "Alice" || x.Name == "Bob");
await foreach (var employee in AliceOrBobs)
{
    Console.WriteLine($"{employee.Name} is {employee.Age} years old and works in the {employee.Department} Department");
}

限制结果对象字段#

当您在 Redis 中查询更大的文档时,您可能不希望通过网络拖回整个对象,在这种情况下,您可以使用 Select 谓词将结果限制为您想要的内容。例如,如果您只想找出员工的年龄,您只需选择员工的年龄即可

var employeeAges = employees.Select(x => x.Age);
await foreach (var age in employeeAges)
{
    Console.WriteLine($"age: {age}");
}

或者,如果您想选择多个字段,您可以创建一个新的匿名对象

var employeeAges = employees.Select(x => new {x.Name, x.Age});
await foreach (var e in employeeAges)
{
    Console.WriteLine($"{e.Name} is age: {e.Age} years old");
}

限制返回的对象#

您可以使用 SkipTake 谓词来限制结果的大小(以返回的对象数量为单位)。Skip 将跳过指定数量的记录,而 Take 将最多只获取提供的数量的记录;

var people = employees.Skip(1).Take(2);
await foreach (var e in people)
{
    Console.WriteLine($"{e.Name} is age: {e.Age} years old");
}

有两种类型的属性可以修饰字符串,Indexed(我们已经讨论过了)和 Searchable(我们尚未讨论)。Searchable 属性对等式的考虑方式与 Indexed 略有不同,它是基于全文搜索的。在涉及 Searchable 字段的表达式中,相等——==——表示匹配。在 Searchable 字段的上下文中,匹配不一定完全匹配,而是字符串包含搜索文本。让我们来看一些示例。

查找销售部门的员工#

所以我们有一个 Department 字符串,它在我们的 Employee 类中被标记为 Searchable。注意我们是如何命名部门的。它们包含一个区域和一个部门类型。如果我们只想找到所有在 Sales 部门的员工,我们可以用以下方法做到这一点

var salesPeople = employees.Where(x => x.Department == "Sales");
await foreach (var employee in salesPeople)
{
    Console.WriteLine($"{employee.Name} is in the {employee.Department} department");
}

这将产生

Bob is in the EMEA Sales department
Alice is in the Partner Sales department
Marcus is in the NA Sales department
Susan is in the EMEA Sales department
John is in the APAC Sales department

因为它们都是部门名称为 sales 的员工

如果您想搜索 EMEA 中部门的每个人,您可以使用以下方法进行搜索

var emeaFolks = employees.Where(x => x.Department == "EMEA");
await foreach (var employee in emeaFolks)
{
    Console.WriteLine($"{employee.Name} is in the {employee.Department} department");
}

这当然会产生

Bob is in the EMEA Sales department
Susan is in the EMEA Sales department
Theresa is in the EMEA Ops department

排序#

如果一个 SearchableIndexed 字段被标记为 SortableAggregatable,则可以使用 OrderBy 谓词按该字段排序。

var employeesBySales = employees.OrderBy(x=>x.Name);
var employeesBySalesDescending = employees.OrderByDescending(x=>x.Name);