将 STRUCT 的 ARRAY 传递给标准 BigQuery SQL 的用户定义函数

Posted

技术标签:

【中文标题】将 STRUCT 的 ARRAY 传递给标准 BigQuery SQL 的用户定义函数【英文标题】:Passing ARRAY of STRUCTs into user-defined function for standard BigQuery SQL 【发布时间】:2017-01-17 10:53:52 【问题描述】:

如何将一个 STRUCTS 数组传递给我的用户定义函数(使用标准 SQL)?

首先,一点上下文:

表架构:

id STRING
customer STRING
request STRUCT<
  headers STRING
  body STRING
  url STRING
>
response STRUCT<
  size INT64
  body STRING
>
outgoing ARRAY<
  STRUCT<
    request STRUCT<
      url STRING,
      body STRING,
      headers STRING
    >,
    response STRUCT<
      size INT64,
      body STRING
    >
  >
>

用户自定义函数:

CREATE TEMPORARY FUNCTION extractDetailed(
  customer STRING,
  request STRUCT<
    headers STRING,
    body STRING
  >,
  outgoing ARRAY<
    STRUCT<
      request STRUCT<url STRING>,
      response STRUCT<body STRING>
    >
  >
)
RETURNS STRING
LANGUAGE js AS """

""";

SELECT extractDetailed(customer, STRUCT(request.headers, request.body), outgoing)
FROM request_logs

至于我的问题:我似乎无法弄清楚如何选择outgoing ARRAY 的一部分,并将其作为数组传递给用户定义的函数。

实际上,我正在尝试模拟以下用户定义的函数调用:

extractDetailed(
  "customer id",
   "headers": "", "body": "" ,
  [
    
      "request":  "url": "" ,
      "response":  "body": "" 
    ,
    
      "request":  "url": "" ,
      "response":  "body": "" 
    
  ]
);

我最近偶然发现了some documentation that might help 解锁它,我似乎无法弄清楚如何使它适合。我真的在为此苦苦挣扎,如果能帮助我解决这个问题,我将不胜感激。

【问题讨论】:

【参考方案1】:

试试下面。它从您的数组中解析所需的和平,并在传递给函数之前将它们放回新数组中,以便匹配 sugnature

CREATE TEMPORARY FUNCTION extractDetailed(
customer STRING,
request STRUCT<headers STRING, body STRING>,
outgoing ARRAY<STRUCT<request STRUCT<url STRING>, response STRUCT<body STRING>>>
)
RETURNS STRING
LANGUAGE js AS """

""";

SELECT 
  extractDetailed(
    customer, 
    STRUCT(request.headers, request.body), 
    ARRAY(
      SELECT STRUCT<request STRUCT<url STRING>,response STRUCT<body STRING>>
          (STRUCT(request.url), STRUCT(response.body)) 
      FROM UNNEST(outgoing)
    )
  ) AS details
FROM request_logs  

为了进一步“优化”上述查询并使其更具可移植性,您可以将原始数组中的提取部分包装到新数组中,并将其包装到单独的 SQL UDF 中

CREATE TEMPORARY FUNCTION extractParts (
  outgoing ARRAY<STRUCT<request STRUCT<url STRING, body STRING, headers STRING>,
                        response STRUCT<size INT64, body STRING>>>
)
RETURNS ARRAY<STRUCT<request STRUCT<url STRING>, response STRUCT<body STRING>>>
AS ((
  SELECT ARRAY(
      SELECT STRUCT<request STRUCT<url STRING>,response STRUCT<body STRING>>
          (struct(request.url), struct(response.body)) 
      FROM UNNEST(outgoing)
    )
));

CREATE TEMPORARY FUNCTION extractDetailed(
  customer STRING,
  request STRUCT<headers STRING, body STRING>,
  outgoing ARRAY<STRUCT<request STRUCT<url STRING>, response STRUCT<body STRING>>>
)
RETURNS STRING
LANGUAGE js AS """
  return outgoing.length;
""";

SELECT 
  extractDetailed(
    customer, 
    STRUCT(request.headers, request.body),
    extractParts(outgoing)
  ) as details
FROM request_logs

【讨论】:

那么,从性能上看,两者有什么区别吗?我对拥有两个 UDF 的第一个想法是它会导致轻微的减速。但我猜这可能是便携性和性能之间的权衡。 根据我的经验,SQL UDF 并没有增加速度。 JS UDF 可以。所以,我觉得上面两个应该执行相同的

以上是关于将 STRUCT 的 ARRAY 传递给标准 BigQuery SQL 的用户定义函数的主要内容,如果未能解决你的问题,请参考以下文章

将struct数组传递给输入函数

Swift - 将struct数组传递给另一个struct的init

将 char*[] 从 c++ dll Struct 传递给 c#

将struct *从c#传递给c ++ dll

使用Struct将String数组和索引传递给C中的线程

无法将提示中的多个值传递给 Bi Publisher 11g