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

从KDB中包含JSON文本的列中提取多个列,kdb,Kdb,我有一个表,其中包含一个包含JSON文本的列。我想解析该列并将不同的属性提取到多个列中 c:([] date:2?.z.d ; client:( "{ \"firstName\": \"John\", \"lastName\": \"Smith\", \"age\": 27 }" ; "{ \"firstName\": \"Scott\", \"lastName\": \"Tiger\", \"age\":29 }" ) ) 尽管JSON解析已经集成到KDB“.j”命名空间(3.

我有一个表,其中包含一个包含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
表、
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'[xy]
将解析和json数据提取到一个表中,使用,
((),z)
只提取所需的列,然后使用
x'
将这些列连接到原始表中。最后一步是使用
((),y)
访问json列


take和drop操作都需要使用
(),
,因为它们希望传递一个列表,这确保了这一点。

据我所知,您对保持客户列的原样不感兴趣。我会这样做:

((),`client) _ c,'{.j.k x}'[exec client from c]
你会得到一张这样的桌子:

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

如果您在表中的每个json上执行.j.k,您将得到一个类似于表的字典列表

q)exec .j.k each client from c
firstName lastName age
----------------------
"John"    "Smith"  27 
"Scott"   "Tiger"  29 
然后,您可以将其连接到原始表并提取您喜欢的任何数据

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效率更高

// 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捕获通常是这样的,即数据和消息是无模式/非结构化的。如果是这种情况,并且每个json字符串不一定具有与其他字符串相同的标记,那么您可以创建所需输出的静态映射,并将该映射连接到每个解析的json消息。这将产生始终解析为表的效果。您还可以键入地图以确保结果表的键入正确

// 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
嗯,肖恩