2017-07-19 58 views
1

我在BigQuery中有一列包含URL查询字符串,例如a=1&c=1。我想在我的查询中引用其中的一些,例如。用类似WHERE querystring.c = 1的东西过滤。BigQuery中的QueryString解析

我的计划是将查询字符串转换为JSON,然后使用JSON_EXTRACT。我想我可以编写一个UDF来将查询字符串转换为JSON,但是我仍然无法解决将node.js querystring package导入到我的UDF中的问题。

是否可以将一个node.js核心库导入到UDF中,如果是这样,如何实现?或者,有没有更好的方法来实现我想要做的?

回答

1

另外还有更好的方法来实现我想要做的?

我想 - 是的 - 使用JS UDF是昂贵的资源明智,并有一定的局限性。使用SQL UDF是更便宜,如果你愿意,你可以通过使用SQL UDF低于转变 - 但至少列出了你的“另类”的方式

对于上面的BigQuery标准SQL

#standardSQL 
WITH yourTable AS (
    SELECT 1 AS id, 'a=1&c=1' AS querystring UNION ALL 
    SELECT 2, 'c=2&b=3' 
) 
SELECT 
    id, 
    querystring, 
    SPLIT(kv, '=')[SAFE_OFFSET(0)] AS key, 
    SPLIT(kv, '=')[SAFE_OFFSET(1)] AS value 
FROM yourTable, UNNEST(SPLIT(querystring, '&')) AS kv 

允许理念你“解压”的所有键值对,像这样,现在下面

id querystring key value  
2 c=2&b=3  b 3  
1 a=1&c=1  c 1  
1 a=1&c=1  a 1  
2 c=2&b=3  c 2  

您可以在使用它们的WHERE子句像下面

#standardSQL 
WITH yourTable AS (
    SELECT 1 AS id, 'a=1&c=1' AS querystring UNION ALL 
    SELECT 2, 'c=2&b=3' 
) 
SELECT 
    id, 
    querystring, 
FROM yourTable, UNNEST(SPLIT(querystring, '&')) AS kv 
WHERE SPLIT(kv, '=')[SAFE_OFFSET(0)] = 'c' 
AND SPLIT(kv, '=')[SAFE_OFFSET(1)] = '1' 

这给了下面的结果

id querystring 
1 a=1&c=1  

注:这是方法只是快速和抽象插图 - 我希望你能调整/它采用您的具体情况

下面是上面的例子来转化的使用SQL UDF

#standardSQL 
CREATE TEMPORARY FUNCTION parse(qs STRING, key STRING) AS (
    (SELECT SPLIT(kv, '=')[SAFE_OFFSET(1)] FROM UNNEST(SPLIT(qs, '&')) AS kv WHERE SPLIT(kv, '=')[SAFE_OFFSET(0)] = key) 
); 
WITH yourTable AS (
    SELECT 1 AS id, 'a=1&c=1' AS querystring UNION ALL 
    SELECT 2, 'c=2&b=3' 
) 
SELECT 
    id, 
    querystring 
FROM yourTable 
WHERE parse(querystring, 'c') = '1' 

注:一般的查询字符串没有钥匙的重复 - 因此拥有了DUP情况下没有解决 - 但容易,如果需要:O)

但它不解码任何编码的组件,所以我的值仍然包含像%20这样的东西。对此有何建议?

#standardSQL 
CREATE TEMPORARY FUNCTION parse(qs STRING, key STRING) AS (
    (SELECT SPLIT(kv, '=')[SAFE_OFFSET(1)] FROM UNNEST(SPLIT(qs, '&')) AS kv WHERE SPLIT(kv, '=')[SAFE_OFFSET(0)] = key) 
); 
CREATE TEMP FUNCTION decode(str STRING) 
RETURNS STRING 
LANGUAGE js AS """ 
    if (str == null) return null; 
    try { 
    return decodeURIComponent(str); 
    } catch (e) { 
    return str; 
    } 
"""; 
WITH yourTable AS (
    SELECT 1 AS id, 'a=1&c=1&d=a%20b%20c' AS querystring UNION ALL 
    SELECT 2, 'c=2&b=3' 
) 
SELECT 
    id, 
    querystring, 
    decode(parse(querystring, 'd')) as d 
FROM yourTable 
WHERE parse(querystring, 'c') = '1' 

结果是

id querystring    d  
-- -------------------  ----- 
1 a=1&c=1&d=a%20b%20c  a b c  
+0

这是一个很好的方法,但它不解码任何编码的组件,所以我的价值观仍将包含之类的东西20%。对此有何建议? –

+0

好点。我对待你的问题更像是如何从查询字符串中解析/提取键/值。在一个答案中很难涵盖所有的细微差别。我建议你问一个新的问题具体到url解码 - 我没有看到这个问题 - 所以你有很好的机会得到答案 - 但正如我所说,期望涵盖所有细微差异在一个职位是不现实的:o) –

+0

在我的答案中看到更新:o)。 –