【问题标题】:QueryString parsing in BigQueryBigQuery 中的 QueryString 解析
【发布时间】:2017-12-25 10:55:56
【问题描述】:

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

我的计划是将查询字符串转换为 JSON,然后使用 JSON_EXTRACT。我想我可以编写一个 UDF 将查询字符串转换为 JSON,但无论如何我都无法将 node.js querystring package 导入我的 UDF 以简化此操作。

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

【问题讨论】:

    标签: google-bigquery user-defined-functions


    【解决方案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   
    

    above 允许您“提取”所有键值对,如下所示

    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'
    

    注意:通常查询字符串没有键重复 - 因此没有解决重复的情况 - 但如果需要很容易: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    
    

    【讨论】:

    • 这是一个很好的方法,但它不会解码任何编码的组件,所以我的值仍然会包含 %20 之类的东西。对此有何建议?
    • 好点。我对待您的问题更像是如何从查询字符串中解析/提取键/值。很难在一个答案中涵盖所有细微差别。我建议您提出特定于 url 解码的新问题-我认为这没有问题-因此您有很好的机会获得答案-但正如我所说,期望在一篇文章中涵盖所有细微差别是不现实的 :o)
    猜你喜欢
    • 2015-04-11
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    • 2022-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    相关资源
    最近更新 更多