UQL Parser
UQL(非结构化查询语言)是 Infinity 数据源中的一种高级查询格式,它可以整合 JSON、CSV、XML、GraphQL 格式。UQL 还提供了定制结果的能力。
UQL 是一种专门为内存操作设计的查询语言。UQL 查询可以通过一系列用 |
连接的命令构成,每行一个。大多数情况下,字段使用双引号引用,字符串值使用单引号引用。UQL 的灵感来源于 kusto 查询语言,并遵循类似的语法。
注意
UQL 仍处于测试阶段,但已被广泛使用。如果您在使用 UQL 时遇到任何问题,请在 GitHub 上提交 bug。
如果您的数据看起来像这样
[
{
"id": 1,
"name": { "firstName": "john", "lastName": "doe" },
"dob": "1985-01-01",
"city": "chennai"
},
{
"id": 2,
"name": { "firstName": "alice", "lastName": "bob" },
"dob": "1990-12-31",
"city": "london"
}
]
那么以下 UQL 查询
parse-json
| extend "full name"=strcat("name.firstName",' ',"name.lastName"), "dob"=todatetime("dob")
| project-away "name"
| order by "full name" asc
将生成一个包含四列的表格 (id, dob, city, full name)。
基本 UQL 命令
除非另有说明,所有版本都提供这些命令。
project
project
命令用于选择要在结果中包含的列。如果您想选择嵌套对象内的属性,可以使用点记法。您还可以选择为字段设置别名。
parse-json
| project "id", "name.firstName", "date of birth"="dob"
project-away
project-away
命令与 project
命令完全相反。它只是从数据中删除特定的列。它不支持别名或点记法选择器。
parse-json
| project-away "id", "city"
order by
order by
命令根据任何列对输入进行排序。排序方向应为 asc
或 desc
parse-json
| order by "full name" asc
extend
extend
命令类似于 project
。但它不是选择列,而是向现有数据添加/替换列。extends
需要一个别名和一个函数。
parse-json
| extend "dob"=todatetime("dob"), "city"=toupper("city")
以下是一些可用函数
函数关键字 | 语法 | 描述 | 可用于 |
---|---|---|---|
trim | trim(“name”) | 修剪字符串 | 0.8.0 |
trim_start | trim_start(“name”) | 移除前面的空格 | 0.8.0 |
trim_end | trim_end(“name”) | 移除后面的空格 | 0.8.0 |
tonumber | tonumber(“age”) | 将字符串转换为数字 | 0.8.0 |
tostring | tostring(“age”) | 将数字转换为字符串 | 0.8.0 |
todatetime | todatetime(“age”) | 将日期时间字符串转换为日期时间 | 0.8.0 |
unixtime_seconds_todatetime | unixtime_seconds_todatetime(“dob”) | 将 Unix epoch 秒时间戳转换为日期时间 | 0.8.0 |
unixtime_nanoseconds_todatetime | unixtime_nanoseconds_todatetime(“dob”) | 将 Unix epoch 纳秒时间戳转换为日期时间 | 0.8.0 |
unixtime_milliseconds_todatetime | unixtime_milliseconds_todatetime(“dob”) | 将 Unix epoch 毫秒时间戳转换为日期时间 | 0.8.0 |
unixtime_microseconds_todatetime | unixtime_microseconds_todatetime(“dob”) | 将 Unix epoch 微秒时间戳转换为日期时间 | 0.8.0 |
format_datetime | format_datetime(“dob”,‘DD/MM/YYYY’) | 将日期时间转换为特定格式 | 0.8.0 |
add_datetime | add_datetime(“dob”,’-1d') | 向日期时间字段添加持续时间 | 0.8.0 |
startofminute | startofminute(“dob”) | 将日期时间字段四舍五入到起始分钟 | 0.8.0 |
startofhour | startofhour(“dob”) | 将日期时间字段四舍五入到起始小时 | 0.8.0 |
startofday | startofday(“dob”) | 将日期时间字段四舍五入到起始天 | 0.8.0 |
startofmonth | startofmonth(“dob”) | 将日期时间字段四舍五入到起始月 | 0.8.0 |
startofweek | startofweek(“dob”) | 将日期时间字段四舍五入到起始周 | 0.8.0 |
startofyear | startofyear(“dob”) | 将日期时间字段四舍五入到起始年 | 0.8.0 |
extract | extract(‘regex’,index,“col1”) | 使用 regex 和匹配索引 (0/1/..) 提取字符串字段的一部分 | 1.0.0 |
sum | sum(“col1”,“col2”) | 两个或多个列的和 | 0.8.0 |
diff | diff(“col1”,“col2”) | 两个列的差 | 0.8.0 |
mul | mul(“col1”,“col2”) | 两个列的乘积 | 0.8.0 |
div | div(“col1”,“col2”) | 两个列的除法 (col1/col2) | 0.8.0 |
percentage | percentage(“col1”,“col2”) | 两个列的百分比 ((col1/col2)*100) | 1.0.0 |
strcat | strcat(“col1”,“col2”) | 连接两个或多个列 | 0.8.0 |
split | split(“col1”,‘delimiter’) | 使用分隔符分割字符串 | 1.0.0 |
replace_string | replace_string(“col1”,‘src’,‘replacer’) | 用另一个字符串替换字符串的一部分 | 1.0.0 |
reverse | revers(“col1”) | 反转字符串 | 1.0.0 |
floor | floor(“col1”) | 计算给定数值字段的向下取整值 | 0.8.7 |
ceil | ceil(“col1”) | 计算给定数值字段的向上取整值 | 0.8.7 |
round | round(“col1”) | 计算给定数值字段的四舍五入值 | 0.8.7 |
sign | sign(“col1”) | 计算给定数值字段的符号值 | 0.8.7 |
pow | pow(“col1”,3) | 计算给定数值字段的幂值 | 0.8.7 |
sin | sin(“col1”) | 计算给定数值字段的正弦值 | 0.8.7 |
cos | cos(“col1”) | 计算给定数值字段的余弦值 | 0.8.7 |
tan | tan(“col1”) | 计算给定数值字段的正切值 | 0.8.7 |
log | log(“col1”) | 计算给定数值字段的对数值 | 0.8.7 |
log2 | log2(“col1”) | 计算给定数值字段的 log2 值 | 0.8.7 |
log10 | log10(“col1”) | 计算给定数值字段的 log10 值 | 0.8.7 |
parse_url | parse_url(“col1”) | 将 col1 解析为 URL | 0.8.6 |
parse_url(“col1”,‘pathname’) | 返回 URL 的 pathname 。选项包括 host 、hash 、origin 、href 、protocol 和 search | 0.8.6 | |
parse_url(“col1”,‘search’,‘key1’) | 返回 key1 的查询字符串值。第二个参数始终为 search | 0.8.6 | |
atob | atob(“col1”) | 返回字符串列的 atob 值。参考 | 1.3.0 |
btoa | btoa(“col1”) | 返回字符串列的 btoa 值。参考 | 1.3.0 |
substring | substring(“col1”,1,5) | 返回字符串列的 substring 值。参考 | 1.3.0 |
例如,数据 [ { "a": 12, "b" : 20 }, { "a" : 6, "b": 32} ]
和以下 uql 查询
parse-json
| project "a", "triple"=sum("a","a","a"),"thrice"=mul("a",3), sum("a","b"), diff("a","b"), mul("a","b")
将生成以下输出
a | 三倍 | 三倍 | sum | diff | mul |
---|---|---|---|---|---|
12 | 36 | 36 | 32 | -8 | 240 |
6 | 18 | 18 | 38 | -26 | 192 |
要对字段应用多个转换,请使用相同的字段名重复它们。例如,uql 查询 extend "name"=tolower("name"), "name"=trim("name")
将对 name 字段先应用 tolower 函数,然后应用 trim 函数。
还有一些其他的 extend/project 方法可用于处理数组
pack
pack 方法将键值对数组转换为 map。例如 extend "foo"=pack('key1',"value1",'key1',"value2")
将生成对象 {key1:value1,key2:value2}
array_from_entries
array_from_entries 方法从条目构建对象数组。例如 extend "foo"=array_from_entries('timestamp',[2010,2020,2030])
将生成数组 [{timestamp:2010},{timestamp:2020},{timestamp:2030}]
array_to_map
array_to_map 将条目数组转换为 map。可以选择为键提供别名而不是索引。例如 extend "foo"=array_to_map(['chennai','india'],'city','country')
将生成 { 'city': 'chennai', 'country':'india'}
summarize
summarize
命令按字符串列聚合数据。summarize 命令需要别名、summarize 字段和 summarize 函数。以下是有效的 summarize 函数。
函数关键字 | 语法 | 描述 | 可用于 |
---|---|---|---|
count | count() | 值的计数 | 0.8.0 |
sum | sum(“age”) | 年龄的总和 | 0.8.0 |
min | min(“population”) | 人口的最小值 | 0.8.0 |
max | max(“foo”) | foo 的最大值 | 0.8.0 |
mean | mean(“foo”) | foo 的平均值 | 0.8.0 |
例如,以下数据
[
{ "city": "tokyo", "country": "japan", "population": 200 },
{ "city": "newyork", "country": "usa", "population": 60 },
{ "city": "oslo", "country": "usa", "population": 40 },
{ "city": "new delhi", "country": "india", "population": 180 },
{ "city": "mumbai", "country": "india", "population": 150 }
]
以及以下 uql 查询
parse-json
| summarize "number of cities"=count(), "total population"=sum("population") by "country"
| extend "country"=toupper("country")
| order by "total population" desc
将生成如下输出表
国家 | 城市数量 | 总人口 |
---|---|---|
INDIA | 2 | 330 |
JAPAN | 1 | 200 |
USA | 2 | 100 |
pivot
pivot
是用于对数据执行透视操作的命令。pivot
命令接受 3 个参数。
- 第一个参数是摘要。示例:
count("id)
或sum("salary")
- 第二个参数是行字段名。示例:
"country"
- 第三个参数是列字段名。示例:
"occupation"
Pivot 示例 1
name,age,country,occupation,salary
Leanne Graham,38,USA,Devops Engineer,3000
Ervin Howell,27,USA,Software Engineer,2300
Clementine Bauch,17,Canada,Student,
Patricia Lebsack,42,UK,Software Engineer,2800
Leanne Bell,38,USA,Senior Software Engineer,4000
Chelsey Dietrich,32,USA,Software Engineer,3500
以及以下查询
parse-csv
| extend "salary"=tonumber("salary")
| pivot sum("salary"), "country", "occupation"
将生成
国家 | Devops Engineer | Software Engineer | Student | Senior Software Engineer |
---|---|---|---|---|
USA | 3000 | 5800 | 0 | 4000 |
CANADA | 0 | 0 | 0 | 0 |
UK | 0 | 2800 | 0 | 0 |
而以下 summarize 查询
parse-csv
| extend "salary"=tonumber("salary")
| summarize "salary"=sum("salary") by "country", "occupation"
将生成
国家 | occupation | salary |
---|---|---|
USA | Devops Engineer | 3000 |
USA | Software Engineer | 5800 |
Canada | Student | 0 |
UK | Software Engineer | 2800 |
UK | Senior Software Engineer | 4000 |
因此,根据您的需要选择 summarize
或 pivot
parse-json
parse-json
命令用于指示 UQL 将响应解析为 JSON
parse-csv
parse-csv
命令用于指示 UQL 将响应解析为 CSV
parse-xml
parse-xml
命令用于指示 UQL 将响应解析为 XML
parse-yaml
parse-yaml
用于指定结果为 YAML 格式
count
count
parse-json
| count
count 提供结果的数量。
limit
parse-json
| limit 10
limit
命令限制返回结果的数量。例如,以下查询只返回 10 个结果
scope
scope
命令设置输出数据的上下文。当结果位于嵌套的 json 对象内部时很有用。
{
"meta": { "last-updated": "2021-08-09" },
"count": 2,
"users": [{ "name": "foo" }, { "name": "bar" }]
}
示例
parse-json
| scope "users"
以下 uql 查询仅返回“users”并忽略其他根级别属性。
mv-expand
[
{ "group": "A", "users": ["user a1", "user a2"] },
{ "group": "B", "users": ["user b1"] }
]
mv-expand
将多值属性扩展为独立的记录。例如,对以下数据使用命令 mv-expand "user"="users"
[
{ "group": "A", "user": "user a1" },
{ "group": "A", "user": "user a2" },
{ "group": "B", "user": "user b1" }
]
将生成如下结果
mv-expand
也应适用于非字符串数组。
project kv()
project kv()
命令用于将给定的对象转换为键值对。
示例:对于数据 { "a": {"name":"a1"}, "b": {"name":"b1"}, "c": {"name":"c1"} } 和查询 parse-json | project kv() 将生成以下表格 | 键 |
---|---|
a | 值 |
{"name":"a1"} | b |
{"name":"b1"} | c |
{"name":"c1"}
此命令也可与参数一起使用
示例:对于数据
{ "data": { "a": {"name":"a1"}, "b": {"name":"b1"}, "c": {"name":"c1"} } }
和查询parse-json | project kv("data")
将生成相同的结果
project kv() 命令仅在插件 0.8.7 及以上版本中可用
JSONata
parse-json
| scope "library"
| jsonata "library.loans@$L.books@$B[$L.isbn=$B.isbn].customers[$L.customer=id].{ 'customer': name, 'book': $B.title, 'due': $L.return}"
| count
jsonata
命令接受一个 JSONata 查询并应用于先前的输入
像任何其他命令一样,
jsonata
命令可以与多个命令组合/通过管道连接。您也可以使用 JSONata 进行数据过滤。
从 0.8.8 版本开始支持 JSONata
注释