从 KDB 中包含 JSON 文本的列中提取多列

Extracting multiple columns from a column containing JSON text in KDB

我有一个 table,其中包含一个包含 JSON 文本的列。我想解析该列并将不同的属性提取到多个列。

c:([] date:2?.z.d ;  client:( "{  \"firstName\": \"John\",  \"lastName\": \"Smith\", \"age\": 27 }" ; "{  \"firstName\": \"Scott\",  \"lastName\": \"Tiger\", \"age\":29 }" ) )  

尽管 JSON 解析已经集成到 KDB '.j' 命名空间(3.3 及更高版本)中。 可以使用 .j.k.

解析
select date, firstName:client@\:`firstName , lastName:client@\:`lastName from update .j.k each client from  c

您可以使用 '.j.j' 将 kdb 对象序列化为表示 JSON.

的字符串

假设您想在提取数据后删除客户列,您可以使用以下函数,它有 3 个参数 - x table、y json 列和 z 要提取的列:

q)f:{((),y)_x,'((),z)#.j.k'[x y]}
q)f[c;`client;`firstName]
date       firstName
--------------------
2008.02.04 "John"
2015.01.02 "Scott"

这可以分解如下:.j.k'[x y] 将使用 .j.k, ((),z)# uses the take operator # to extract only the required columns, which are then joined to the original table with x,'. The final step is to drop _ 和 json 列将解析和 json 数据提取到 table 中((),y)_.

获取和删除操作都需要使用 (),,因为它们希望传递一个列表,这确保了这种情况。

据我了解,您对保持客户栏的原样不感兴趣。我会这样做:

((),`client) _ c,'{.j.k x}'[exec client from c]

你会得到一个像这样的table:

date       firstName lastName age
---------------------------------
2003.07.05 "John"    "Smith"  27
2005.02.25 "Scott"   "Tiger"  29

如果您在 table 中的每个 json 上执行 .j.k ,您将得到一个类似于 table;

q)exec .j.k each client from c
firstName lastName age
----------------------
"John"    "Smith"  27 
"Scott"   "Tiger"  29 

然后您可以将其加入您的原始 table 并提取您喜欢的任何数据;

q)foo:(,'/)(c; exec .j.k each client from c)
q)select date, firstName, lastName, age from foo
date       firstName lastName age
---------------------------------
2008.02.04 "John"    "Smith"  27 
2015.01.02 "Scott"   "Tiger"  29 

这是从整个 json 列创建单个 json 数组的替代方法。

运行 .j.k 在单个字符串上比 运行 .j.k 在许多小 arrays/dictionaries/strings.

上更有效
// test table
q)c:([] date:2?.z.d ;  client:( "{  \"firstName\": \"John\",  \"lastName\": \"Smith\", \"age\": 27 }" ; "{  \"firstName\": \"Scott\",  \"lastName\": \"Tiger\", \"age\":29 }" ) );
// combine each string with "," and encompass in "[]"
// join each parsed dictionary with each row from c, keep client column for keep sake
q)c,'exec .j.k {"[",x,"]"}"," sv client from c

通常是 json 捕获的情况,数据和消息是 schemaless/unstructured。如果是这种情况并且每个 json 字符串不一定具有与其他字符串相同的标签,那么您可以创建所需输出的静态映射并将该映射连接到每个已解析的 json 消息。这将产生始终解析为 table 的效果。您还可以键入地图以确保正确键入结果 table。

// insert row with missing age tag and new location tag
q)`c insert (.z.d;"{\"firstName\": \"Sean\", \"lastName\": \"O'Hagan\", \"location\" : \"Dub\"}");
// name and locations are strings, age is float
q)map:{x,'first each x$\:()}[`firstName`lastName`age`location!10 10 9 11h];
// manually edit symbol nulls to be varchars, so when casting to symbol the RHS param is always a varchar
q).[`map;where map[;1]~\:`;:;(-11h;" ")];
// join map to each parsed dictionary, and delete client column as we have extracted useful data
q)delete client from c,'exec flip map[;0]$flip (map[;1],/:.j.k {"[",x,"]"}"," sv client) from c
date       firstName lastName  age location
-------------------------------------------
2004.02.01 "John"    "Smith"   27
2005.06.06 "Scott"   "Tiger"   29
2018.03.13 "Sean"    "O'Hagan"     Dub
q)meta delete client from c,'exec flip map[;0]$flip (map[;1],/:.j.k {"[",x,"]"}"," sv client) from c
c        | t f a
---------| -----
date     | d
firstName| C
lastName | C
age      | f
location | s

HTH,肖恩