学习

应用函数是您可以定义为表达式以应用于 Redis 中数据的函数。从本质上讲,它们允许您将数据组合在一起,并提取所需的信息。

数据模型#

在本文的其余部分中,我们将使用此数据模型

[Document]
public class Employee
{
    [Indexed(Aggregatable = true)]
    public string Name { get; set; }

    [Indexed]
    public GeoLoc? HomeLoc { get; set; }

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

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

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

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

    [Indexed(Aggregatable = true)]
    public long LastOnline { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}

应用函数的剖析#

ApplyRedisAggregationSet<T> 类上的一个方法,它接受两个参数,每个参数都是应用函数的一个组件。

首先,它接受您希望 Redis 在管道中的每条记录上执行的表达式,该表达式接受一个参数,即 AggregationResult<T>,其中 TRedisAggregationSet 的泛型类型。此 AggregationResult 有两件事我们应该考虑,首先它包含一个 RecordShell,它是泛型类型的占位符,其次它有一个 Aggregations 属性 - 它是一个包含来自管道结果的字典。这两者都可以在应用函数中使用。

第二个组件是别名,它是管道执行时函数结果存储的名称。

调整后的销售额#

我们的数据模型有两个与销售额相关的属性,Sales,表示员工的销售额,以及 SalesAdjustment,一个用于根据各种因素(可能是覆盖区域、经验等)调整销售额的数字。其理念是,也许分析员工绩效的公平方法是结合这两个字段,而不是单独分析每个字段。假设我们想找出每个人的调整后销售额,我们可以通过创建一个应用函数来计算它。

var adjustedSales = employeeAggregations.Apply(x => x.RecordShell.SalesAdjustment * x.RecordShell.Sales,
    "ADJUSTED_SALES");
foreach (var result in adjustedSales)
{
    Console.WriteLine($"Adjusted Sales were: {result["ADJUSTED_SALES"]}");
}

算术应用函数#

使用算术和数学的函数可以使用数学运算符 + 进行加法运算,- 进行减法运算,* 进行乘法运算,/ 进行除法运算,以及 % 进行取模运算,此外,通常用于按位异或运算的 ^ 运算符已预留用于幂函数。此外,您可以在 Apply 函数中使用许多 System.Math 库运算,这些运算将转换为适当的方法供 Redis 使用。

可用的数学函数#

函数

类型

描述

示例

Log10

数学

产生数字的 10 为底的对数

Math.Log10(x["AdjustedSales"])

Abs

数学

产生所提供数字的绝对值

Math.Abs(x["AdjustedSales"])

Ceil

数学

产生不小于所提供数字的最小整数

Math.Ceil(x["AdjustedSales"])

Floor

数学

产生不大于所提供数字的最大整数

Math.Floor(x["AdjustedSales"])

Log

数学

产生所提供数字的 2 为底的对数

Math.Log(x["AdjustedSales"])

Exp

数学

产生所提供数字的自然指数 (e^y)

Math.Exp(x["AdjustedSales"])

Sqrt

数学

产生所提供数字的平方根

Math.Sqrt(x["AdjustedSales"])

字符串函数#

您还可以对数据应用多个字符串函数,例如,如果要为每个员工创建生日消息,可以通过调用 String.Format 来实现:

var birthdayMessages = employeeAggregations.Apply(x =>
    string.Format("Congratulations {0} you are {1} years old!", x.RecordShell.Name, x.RecordShell.Age), "message");
await foreach (var message in birthdayMessages)
{
    Console.WriteLine(message["message"].ToString());
}

字符串函数列表:#

函数

类型

描述

示例

ToUpper

字符串

将提供的字符串转换为大写

x.RecordShell.Name.ToUpper()

ToLower

字符串

将提供的字符串转换为小写

x.RecordShell.Name.ToLower()

StartsWith

字符串

布尔表达式 - 如果字符串以参数开头,则产生 1

x.RecordShell.Name.StartsWith("bob")

Contains

字符串

布尔表达式 - 如果字符串包含参数,则产生 1

x.RecordShell.Name.Contains("bob")

Substring

字符串

产生从给定的从 0 开始的索引开始的子字符串,长度为第二个参数,如果没有提供第二个参数,则 simplemente 返回字符串的剩余部分

x.RecordShell.Name.Substring(4, 10)

Format

字符串

根据提供的模式格式化字符串

string.Format("Hello {0} You are {1} years old", x.RecordShell.Name, x.RecordShell.Age)

Split

字符串

使用提供的字符串拆分字符串 - 不幸的是,如果您只传入一个分隔符,由于表达式的运作方式,您需要提供字符串拆分选项,以便在构建表达式时不存在可选参数,只需传递 StringSplitOptions.None

x.RecordShell.Name.Split(",", StringSplitOptions.None)

时间函数#

您还可以在 Redis 中对时间数据执行函数。如果您的时间戳存储为可用格式,例如 Unix 时间戳或可以从 strftime转换的时间戳字符串,则可以对其进行操作。例如,如果要将 Unix 时间戳转换为 YYYY-MM-DDTHH:MM::SSZ 格式,则只需在应用函数内部调用 ApplyFunctions.FormatTimestamp 即可。例如:

var lastOnline = employeeAggregations.Apply(x => ApplyFunctions.FormatTimestamp(x.RecordShell.LastOnline),
    "LAST_ONLINE_STRING");

foreach (var employee in lastOnline)
{
    Console.WriteLine(employee["LAST_ONLINE_STRING"].ToString());
}

可用的时间函数#

函数

类型

描述

示例

ApplyFunctions.FormatTimestamp

时间

根据 strftime 约定将 Unix 时间戳转换为格式化的时间字符串

ApplyFunctions.FormatTimestamp(x.RecordShell.LastTimeOnline)

ApplyFunctions.ParseTime

时间

将提供的格式化时间戳解析为 Unix 时间戳

ApplyFunctions.ParseTime(x.RecordShell.TimeString, "%FT%ZT")

ApplyFunctions.Day

时间

将 Unix 时间戳舍入到当天的开始时间

ApplyFunctions.Day(x.RecordShell.LastTimeOnline)

ApplyFunctions.Hour

时间

将 Unix 时间戳舍入到当前小时的开始时间

ApplyFunctions.Hour(x.RecordShell.LastTimeOnline)

ApplyFunctions.Minute

时间

将 Unix 时间戳舍入到当前分钟的开始时间

ApplyFunctions.Minute(x.RecordShell.LastTimeOnline)

ApplyFunctions.Month

时间

将 Unix 时间戳舍入到当前月的开始时间

ApplyFunctions.Month(x.RecordShell.LastTimeOnline)

ApplyFunctions.DayOfWeek

时间

将 Unix 时间戳转换为星期几,其中星期日为 0

ApplyFunctions.DayOfWeek(x.RecordShell.LastTimeOnline)

ApplyFunctions.DayOfMonth

时间

将 Unix 时间戳转换为当前月的哪一天 (1..31)

ApplyFunctions.DayOfMonth(x.RecordShell.LastTimeOnline)

ApplyFunctions.DayOfYear

时间

将 Unix 时间戳转换为当前年的哪一天 (1..31)

ApplyFunctions.DayOfYear(x.RecordShell.LastTimeOnline)

ApplyFunctions.Year

时间

将 Unix 时间戳转换为当前年份

ApplyFunctions.Year(x.RecordShell.LastTimeOnline)

ApplyFunctions.MonthOfYear

时间

将 Unix 时间戳转换为当前年份

ApplyFunctions.MonthOfYear(x.RecordShell.LastTimeOnline)

地理距离#

另一个很有用的函数是 GeoDistance 函数,它允许您计算两点之间的距离,例如,如果您想查看每个员工离办公室有多远,可以使用管道内的 ApplyFunctions.GeoDistance 函数。

var officeLoc = new GeoLoc(-122.064181, 37.377207);
var distanceFromWork =
    employeeAggregations.Apply(x => ApplyFunctions.GeoDistance(x.RecordShell.HomeLoc, officeLoc), "DistanceToWork");
await foreach (var element in distancesFromWork)
{
    Console.WriteLine(element["DistanceToWork"].ToString());
}
最后更新时间: 2024 年 2 月 19 日