Azure 流分析支持以 JavaScript 编写的用户定义的函数。 通过使用 JavaScript 提供的丰富的 字符串、 规范表达、 数学、 数组和 日期 方法,你可以在流分析作业中创建复杂的数据转换。 JavaScript 用户定义的函数支持仅用于计算的且不需要外部连接的无状态标量函数。 函数的返回值只能是标量(单个)值。 将某个 JavaScript 用户定义的函数添加到作业后,可在查询中的任意位置使用该函数,如同内置标量函数一样。
本文介绍了何时使用JavaScript用户自定义函数,以及如何在你的流分析作业中定义和调用它们。
何时使用JavaScript用户自定义函数
下面是 JavaScript 用户定义的函数可派上用场的一些情景:
- 通过正则表达式函数进行解析和操作,例如, Regexp_Replace() 和 Regexp_Extract()
- 解码和编码数据,例如,二进制到十六进制的转换
- 使用JavaScript 数学函数进行 数学计算
- 执行排序、联接、查找和填充等数组操作
以下是Stream Analytics中使用JavaScript用户自定义函数无法实现的一些功能:
- 例如调用外部REST端点,进行反向IP查询或从外部来源拉取参考数据
- 对输入或输出执行自定义事件格式序列化或反序列化
- 创建自定义聚合
虽然像 Date.GetDate() 或 Math.random() 这样的函数在函数定义中没有被阻挡,但请避免使用它们。 这些函数在每次被调用时不会返回相同的结果,并且 Azure 流分析服务不会保留函数调用和返回结果的日记。 如果函数在相同事件中返回不同的结果,当你或流分析服务重启作业时,重复性就无法保证。
在 Azure 门户中定义 JavaScript 用户自定义函数
对于运行在云端的Stream Analytics作业,可以在作业拓扑下的函数页面添加JavaScript用户自定义函数,其中+添加菜单包含JavaScript UDF选项。
注释
此体验适用于配置为在云端运行的 Stream Analytics 作业。
函数定义包含以下性质:
| 属性 | 说明 |
|---|---|
| 函数别名 | 调用你查询中函数的名称。 |
| 输出类型 | JavaScript 用户自定义函数返回给你的流分析查询的类型。 |
| 函数定义 | 每次在查询中调用 UDF 时都会运行的您的 JavaScript 函数实现。 |
测试和调试 JavaScript UDF 的逻辑
由于Stream Analytics门户不支持调试和测试这些用户自定义函数的逻辑,你可以在任何浏览器中测试和调试JavaScript的UDF逻辑。 当该函数按预期工作时,就可以将其添加到 Stream Analytics 作业中,并直接从查询中调用它。 你也可以用 Visual Studio 的 Stream Analytics 工具,用 JavaScript UDF 测试查询逻辑。
Stream Analytics 将 JavaScript 运行时错误视为致命错误,并通过活动日志显示。 日志可以在你工作的活动日志页面的 Azure 门户中获取。
在查询中调用 JavaScript 用户定义的函数
要在查询中调用JavaScript函数,请使用带有 udf的函数别名。 以下示例展示了一个JavaScript UDF,它在Stream Analytics查询中将十六进制值转换为整数。
SELECT
time,
UDF.hex2Int(offset) AS IntOffset
INTO
output
FROM
InputStream
支持的 JavaScript 对象
Azure 流分析 JavaScript 用户自定义函数支持标准的内置 JavaScript 对象。 这些对象让你的函数无需额外配置即可访问常用的字符串、数学、数组和日期操作。 有关可用对象的完整列表,请参见 全局对象。 由于 Stream Analytics 查询语言和 JavaScript 使用的类型系统不同,Stream Analytics 会在两者之间传递值时对这些值进行转换。
流分析和 JavaScript 类型转换
Stream Analytics 查询语言和 JavaScript 支持不同类型。 下表列出了两者之间的转换映射:
| 流分析 | JavaScript |
|---|---|
| bigint | Number(JavaScript 只能精确呈现最大 2^53 的整数) |
| DateTime | Date(JavaScript 仅支持毫秒) |
| Double | 数字 |
| nvarchar(MAX) | 字符串 |
| 记录 | 对象 |
| Array | Array |
| Null | Null |
以下是从 JavaScript 到 Stream Analytics 的转换:
| JavaScript | 流分析 |
|---|---|
| 编号 | Bigint(如果该数字为整数且介于 long.MinValue 和 long.MaxValue 之间;否则为 double) |
| 日期 | DateTime |
| 字符串 | nvarchar(MAX) |
| 对象 | 记录 |
| Array | Array |
| 空值、未定义 | Null |
| 任何其他类型(例如,函数或错误) | 不支持(导致运行时错误) |
JavaScript 区分大小写,JavaScript 代码中对象字段名称的大小写必须与传入数据中字段名称的大小写保持一致。 兼容级别为1.0的作业会将SQL SELECT语句中的字段转换为小写字母。 在兼容级别为 1.1 及更高版本时,SELECT 语句中的字段其大小写与 SQL 查询中指定的保持一致。
常见功能模式
以下模式展示了使用JavaScript用户自定义函数转换Stream Analytics查询中数据的常见方法。 每个模式都包含函数定义和调用函数的示例查询。
编写要输出的嵌套 JSON
如果后续处理步骤需要使用流分析作业输出作为输入并且要求采用 JSON 格式,可以编写要输出的 JSON 字符串。 以下函数定义调用 JSON.stringify() 函数,打包输入的所有名称/值对,然后将它们写成一个字符串值在输出中。
function main(x) {
return JSON.stringify(x);
}
流分析查询调用该函数,如下例所示。
SELECT
DataString,
DataValue,
HexValue,
UDF.jsonstringify(input) As InputEvent
INTO
output
FROM
input PARTITION BY PARTITIONID
将字符串转换为 JSON 对象以进行处理
如果你有一个字符串字段是 JSON,想把它转换成 JSON 对象以便在 JavaScript UDF 中处理,你可以使用 JSON.parse() 函数创建一个 JSON 对象,然后再用它。 以下函数定义解析字符串,并返回生成对象的一个属性。
function main(x) {
var person = JSON.parse(x);
return person.name;
}
流分析查询调用该函数,如下例所示。
SELECT
UDF.getName(input) AS Name
INTO
output
FROM
input
使用 try/catch 进行错误处理
try/catch 块可以帮助你识别传递给 JavaScript UDF 的格式不正确的输入数据所导致的问题。 以下函数定义使用尝试/捕捉块来处理解析错误。
function main(input, x) {
var obj = null;
try{
obj = JSON.parse(x);
}catch(error){
throw input;
}
return obj.Value;
}
在接下来的示例查询中,你将整个记录作为第一个参数传递,这样如果出现错误,函数可以返回它。
SELECT
A.context.company AS Company,
udf.getValue(A, A.context.value) as Value
INTO
output
FROM
input A
toLocaleString()
JavaScript 中的 toLocaleString 方法返回一个语言敏感字符串,表示调用该方法的日期-时间数据。 虽然 Azure 流分析 只接受 UTC 日期时间作为系统时间戳,但你可以用这种方法将系统时间戳转换为另一个地点和时区。 该方法的实现行为与 Internet Explorer 中的相同。 以下函数定义将输入日期时间转换为 de-DE 位置。
function main(datetime){
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
return datetime.toLocaleDateString('de-DE', options);
}
在以下示例查询中,一个日期时间作为输入值传递。
SELECT
udf.toLocaleString(input.datetime) as localeString
INTO
output
FROM
input
该查询会根据所提供的选项,以 de-DE 格式输出输入的日期时间。
Samstag, 28. December 2019
用户日志记录
日志是 Azure 流分析 用来在作业运行时从JavaScript用户自定义函数中捕获自定义信息的机制。 由于运行中的作业本身是不透明的,日志数据能让你实时看到自定义代码的行为和正确性。 每个日志消息都带有一个事件级别,指示消息的重要性以及作业是否能继续运行。
信息消息来自 console.info() 方法,例如 console.info('my info message');。 该级别在执行过程中记录一般信息,不中断计算。 警告消息来自 console.warn() 方法,例如 console.warn('my warning message');。 此级别会记录可能异常但对于计算而言仍可接受的数据,因此该作业会继续运行。 错误消息来自 console.error() 和 console.log() 方法,例如 console.error('my error message');。 这些方法仅适用于代码无法继续的情况,因此会抛出包含错误信息的异常并停止作业。
可以通过诊断日志访问日志消息。
atob() 和 btoa()
Stream Analytics 支持两种 Base64 转换方法,这是一种将二进制数据编码为文本的常见方式。
btoa() 方法将 ASCII 字符串编码为 Base64,atob() 方法将 Base64 编码数据字符串解码回 ASCII 字符串。 在以下示例中, btoa() 先编码一个ASCII字符串,然后 atob() 将结果解码回原始字符串。
var myAsciiString = 'ascii string';
var encodedString = btoa(myAsciiString);
var decodedString = atob(encodedString);