dynamic 数据类型

dynamic 标量数据类型可以是以下任何值:

  • dynamic 值的数组,其中包含零个或零个以上的值,并从零开始编制索引。
  • 一个属性包,可将唯一的 string 值映射到 dynamic 值。 此属性包有零个或零个以上的此类映射(称为“槽”),通过唯一的 string 值进行索引编制。 这些槽是无序的。
  • 下述任何基元标量数据类型的值:booldatetimeguidintlongrealstringtimespan
  • NULL。 有关详细信息,请参阅 Null 值

注意

  • dynamic 类型的值的限制为 1MB (2^20),未压缩。 如果记录中的单元格值超过 1MB,则该值将被删除并且引入会成功。 可以通过更改列的编码策略来增加列的 MaxValueSize
  • 虽然 dynamic 类型看起来类似于 JSON,但是它可以保存 JSON 模型无法表示的不存在于 JSON 中的值(例如,longrealdatetimetimespanguid)。 因此,在将 dynamic 值序列化为 JSON 表示形式时,JSON 无法表示的值将被序列化为 string 值。 与之相反,Kusto 会将字符串作为强类型值进行分析(如果它们可以这样进行分析)。 这适用于 datetimereallongguid 类型。 有关 JSON 对象模型的详细信息,请参阅 json.org
  • Kusto 不会尝试保留属性包中从名称到值的映射的顺序,因此你不能假定顺序会保留。 例如,将两个具有相同映射集的属性包表示为 string 值时,它们完全有可能产生不同的结果。

动态文本

若要指定 dynamic 文本,请使用以下语法选项之一:

语法 说明 示例
dynamic([value [, ...]]) 由动态文本或其他标量文本构成的数组。 dynamic([1, 2, "hello"])
dynamic({key=value [, ...]}) 一个属性包,或对象。 键的值可以是嵌套属性包。 dynamic({"a":1, "b":{"a":2}})
dynamic(value) 一个动态值,其中包含内部标量数据类型的值。 dynamic(4)
dynamic(null) 表示 null 值

详细了解语法约定

动态对象访问器

若要对字典执行下标操作,请使用点表示法 (dict.key) 或方括号表示法 (dict["key"])。 如果下标为字符串常量,则这两个选项是等效的。

注意

若要使用表达式作为下标,请使用方括号表示法。 使用算术表达式时,方括号内的表达式必须括在圆括号中。

在下面的示例中,dictarr 是 dynamic 类型的列:

表达式 访问器表达式类型 含义 注释
dict[col] 实体名称(列) 使用 col 列的值作为键对字典执行下标操作 列必须为字符串类型
arr[index] 实体索引(列) 使用 index 列的值作为索引对数组执行下标操作 列必须为整数或布尔类型
arr[-index] 实体索引(列) 从数组末尾检索 'index'-th 值 列必须为整数或布尔类型
arr[(-1)] 实体索引 检索数组中的最后一个值
arr[toint(indexAsString)] 函数调用 indexAsString 列的值强制转换为 int,并使用它们对数组执行下标操作
dict[['where']] 用作实体名称(列)的关键字 使用 where 列的值作为键对字典执行下标操作 与某些查询语言关键字相同的实体名称必须用引号引起来
dict.['where'] 或 dict['where'] 常数 使用 where 字符串作为键对字典执行下标操作

提示

建议尽可能使用常数下标。

即使子对象具有不同的基础类型,访问 dynamic 值的子对象也会产生另一个 dynamic 值。 可以使用 gettype 函数查明值的实际基础类型,并使用下面列出的任何类型强制转换函数将其强制转换为实际类型。

强制转换动态对象

对动态对象执行下标操作之后,必须将值强制转换为简单类型。

表达式 类型
X parse_json('[100,101,102]') array
X[0] parse_json('100') dynamic
toint(X[1]) 101 int
Y parse_json('{"a1":100, "a b c":"2015-01-01"}') dictionary
Y.a1 parse_json('100') dynamic
Y["a b c"] parse_json("2015-01-01") dynamic
todate(Y["a b c"]) datetime(2015-01-01) datetime

强制转换函数包括:

  • tolong()
  • todouble()
  • todatetime()
  • totimespan()
  • tostring()
  • toguid()
  • parse_json()

生成动态对象

可以使用多个函数创建新的 dynamic 对象:

  • bag_pack() 通过名称/值对创建属性包。
  • pack_array() 通过名称/值对创建数组。
  • range() 创建一个包含数字算术序列的数组。
  • zip() 将两个数组中的“并行”值配对成一个数组。
  • repeat() 创建一个包含重复值的数组。

此外,还有多个聚合函数可用于创建 dynamic 数组来保存聚合值:

  • buildschema() 返回包含多个 dynamic 值的聚合架构。
  • make_bag() 返回一个在组内包含动态值的属性包。
  • make_bag_if() 返回一个在组内包含动态值的属性包(带谓词)。
  • make_list() 返回一个按顺序保存所有值的数组。
  • make_list_if() 返回一个按顺序保存所有值的数组(带谓词)。
  • make_list_with_nulls() 返回一个按顺序保存所有值(包括 NULL 值)的数组。
  • make_set() 返回一个保存所有唯一值的数组。
  • make_set_if() 返回一个保存所有唯一值的数组(带谓词)。

基于 dynamic 类型的运算符和函数

有关标量动态/数组函数的完整列表,请参阅动态/数组函数

运算符或函数 dynamic 数据类型的用法
valueinarray 如果有 = = value 的 array 元素,则为 true
where City in ('London', 'Paris', 'Rome')
value!inarray 如果没有 = = value 的 array 元素,则为 true
array 如果不是数组,则为 null
bag_has_key(bag,key) 检查动态包列是否包含给定密钥。
bag_keys(bag) 枚举 dynamic 属性包对象中的所有根键。
bag_merge(bag1,...,bagN) 将多个 dynamic 属性包合并成一个包含所有属性的 dynamic 属性包。
bag_set_key(bag,key,value) 将动态属性包中的给定键设置为给定值。
extract_json(path,object), extract_json(path,object) 使用路径导航到对象。
parse_json(source) 将 JSON 字符串转换为动态对象。
range(from,to,step) 一个 值数组。
mv-expand listColumn 为指定单元格列表中的每个值复制一行。
summarize buildschema(column) 根据列内容推断类型架构。
summarize make_bag(column) 将列中的属性包(字典)值合并成一个属性包,无需进行键复制。
summarize make_bag_if(column,predicate) 将列中的属性包(字典)值合并成一个属性包,无需进行键复制(带谓词)。
summarize make_list(column) 平展行组并将列的值放入数组。
summarize make_list_if(column,predicate) 平展行组并将列的值放入数组中(带谓词)。
summarize make_list_with_nulls(column) 平展行组并将列的值(包括 NULL 值)放入数组中。
summarize make_set(column) 平展行组并将列的值放入数组,不进行复制。

动态数据的索引编制

在数据引入期间,每个字段都被索引。 索引范围为单个数据分片。

若要为动态列编制索引,引入过程会枚举动态值中的所有“原子”元素(属性名、值、数组元素),并将它们转发给索引生成器。 否则,动态字段与字符串字段具有相同的倒排词索引。

示例

动态属性包

以下查询创建动态属性包。

print o=dynamic({"a":123, "b":"hello", "c":[1,2,3], "d":{}})
| extend a=o.a, b=o.b, c=o.c, d=o.d

为方便起见,还可以让查询文本自身中出现的 dynamic 文本包含以下类型的其他 Kusto 文本:datetimetimespanreallongguidbooldynamic。 在分析字符串时(例如在使用 parse_json 函数或引入数据时),此基于 JSON 的扩展不可用,但可以通过它执行以下操作:

print d=dynamic({"a": datetime(1970-05-11)})

若要将遵循 JSON 编码规则的 string 值分析为 dynamic 值,请使用 parse_json 函数。 例如:

  • parse_json('[43, 21, 65]') - 数字数组
  • parse_json('{"name":"Alan", "age":21, "address":{"street":432,"postcode":"JLK32P"}}') - 字典
  • parse_json('21') - 包含数字的动态类型的单个值
  • parse_json('"21"') - 包含字符串的动态类型的单个值
  • parse_json('{"a":123, "b":"hello", "c":[1,2,3], "d":{}}') - 提供与上例中的 o 相同的值。

注意

与 JavaScript 不同,JSON 要求使用双引号 (") 字符括住字符串和属性包属性名称。 因此,使用单引号 (') 字符括住 JSON 编码的字符串文本通常更简单。

将数据引入动态列

以下示例展示了如何定义一个保存 dynamic 列(以及 datetime 列)的表,然后将单个记录引入其中。 它还演示了如何对 CSV 文件中的 JSON 字符串进行编码。

// dynamic is just like any other type:
.create table Logs (Timestamp:datetime, Trace:dynamic)

// Everything between the "[" and "]" is parsed as a CSV line would be:
// 1. Since the JSON string includes double-quotes and commas (two characters
//    that have a special meaning in CSV), we must CSV-quote the entire second field.
// 2. CSV-quoting means adding double-quotes (") at the immediate beginning and end
//    of the field (no spaces allowed before the first double-quote or after the second
//    double-quote!)
// 3. CSV-quoting also means doubling-up every instance of a double-quotes within
//    the contents.

.ingest inline into table Logs
  [2015-01-01,"{""EventType"":""Demo"", ""EventValue"":""Double-quote love!""}"]

输出

Timestamp 跟踪
2015-01-01 00:00:00.0000000 {"EventType":"Demo","EventValue":"Double-quote love!"}