Как я могу передать строку из моей таблицы в UDF без указания полного типа?

Допустим, я хочу выполнить некоторую обработку таблицы (например, образца коммитов Github), который имеет вложенную структуру с использованием JavaScript UDF. Я могу захотеть изменить поля, которые я смотрю в UDF, когда я повторяю его реализацию, поэтому я решаю просто передать ему целые строки из таблицы. Мой UDF выглядит примерно так:

#standardSQL
CREATE TEMP FUNCTION GetCommitStats(
  input STRUCT<commit STRING, tree STRING, parent ARRAY<STRING>,
               author STRUCT<name STRING, email STRING, ...>>)
  RETURNS STRUCT<
    parent ARRAY<STRING>,
    author_name STRING,
    diff_count INT64>
  LANGUAGE js AS """
[UDF content here]
""";

Затем я вызываю функцию с таким запросом, как:

SELECT GetCommitStats(t).*
FROM `bigquery-public-data.github_repos.sample_commits` AS t;

Самая громоздкая часть объявления UDF - это структура ввода, так как мне нужно включить все вложенные поля и их типы. Есть лучший способ сделать это?

1 ответ

Решение

Ты можешь использовать TO_JSON_STRING преобразовать произвольные структуры и массивы в JSON, а затем проанализировать их внутри UDF в объект для дальнейшей обработки. Например,

#standardSQL
CREATE TEMP FUNCTION GetCommitStats(json_str STRING)
  RETURNS STRUCT<
    parent ARRAY<STRING>,
    author_name STRING,
    diff_count INT64>
  LANGUAGE js AS """
var row = JSON.parse(json_str);
var result = new Object();
result['parent'] = row.parent;
result['author_name'] = row.author.name;
result['diff_count'] = row.difference.length;
return result;
""";

SELECT GetCommitStats(TO_JSON_STRING(t)).*
FROM `bigquery-public-data.github_repos.sample_commits` AS t;

Если вы хотите сократить количество сканируемых столбцов, вы можете передать структуру соответствующих столбцов в TO_JSON_STRING вместо:

#standardSQL
CREATE TEMP FUNCTION GetCommitStats(json_str STRING)
  RETURNS STRUCT<
    parent ARRAY<STRING>,
    author_name STRING,
    diff_count INT64>
  LANGUAGE js AS """
var row = JSON.parse(json_str);
var result = new Object();
result['parent'] = row.parent;
result['author_name'] = row.author.name;
result['diff_count'] = row.difference.length;
return result;
""";

SELECT
  GetCommitStats(TO_JSON_STRING(
    STRUCT(parent, author, difference)
  )).*
FROM `bigquery-public-data.github_repos.sample_commits`;
Другие вопросы по тегам