Запрос необязательных вложенных полей JSON в Афине - PullRequest
0 голосов
/ 19 апреля 2020

У меня есть json данные, которые выглядят примерно так:

{ "col1" : 123, "metadata" : { "opt1" : 456, "opt2" : 789 } }

, где различные поля метаданных (которых много) являются необязательными и могут присутствовать или не присутствовать.

Мой запрос:

select col1, metadata.opt1 from "db-name".tablename

Если opt1 не присутствует ни в одной строке, я бы ожидал, что он вернет все строки с пробелом для столбца opt1, но если не было строка с opt1 в metadata, когда сканер работал (и может все еще отсутствовать в данных при выполнении запроса, поскольку это необязательно), запрос завершается неудачей, с:

SYNTAX_ERROR: line 2:1: Column '"metadata"."opt1"' cannot be resolved

I можно указать эти поля вручную либо в определении схемы (если я не использую сканер), но тогда он не выберет какие-либо новые поля метаданных, которые могут появиться, и указание схемы stati c не похоже на быть в духе того, как должна работать Афина.

Как мне заставить это работать должным образом (предпочтительно без добавления фиктивных строк или настройки SerDe)?

Использование SerDe org.openx.data.jsonserde.JsonSerDe в настоящее время.

Спасибо за любые идеи.

Ответы [ 2 ]

2 голосов
/ 19 апреля 2020

Возможно, это не то, что вы хотите услышать, но я советую вам не использовать Glue Crawler. Это только верхушка айсберга проблем, которые он создает, когда ваш вариант использования не совсем соответствует сценариям использования, для которых он был разработан (см., Например, этот вопрос , этот вопрос , этот вопрос , этот вопрос или этот вопрос ).

Вместо этого создайте таблицу вручную, используя созданный для вас Glue Crawler. когда это сработало (вы можете получить DDL для таблицы с SHOW CREATE TABLE foo в Афине). Затем добавьте разделы вручную с помощью ALTER TABLE foo ADD PARTITION.

Поддержание в актуальном состоянии таблицы с дополнительными полями будет затруднено, какой бы метод вы ни использовали. Если вы добавляете только когда-либо, вы можете обновить столбцы таблицы, когда добавляете новый раздел, в котором есть больше столбцов (если вы делаете это с Athena, делайте это до того, как добавляете раздел), но другим способом будет просто ввести столбец metadata как STRING и используйте функции JSON для извлечения свойств в ваших запросах (см., например, этот вопрос / ответ ).

Я предполагаю, что вы используете Glue Crawler для добавления разделов периодически. Если вы контролируете процесс добавления данных в S3, я предлагаю вам добавить туда код, который запускает ALTER TABLE … ADD PARTITION (или использует CreatePartition в Glue API.

Если вы не управляете этим кодом, или это было бы очень неудобно, вы можете решить проблему с помощью Lambda. Если вы, например, только разделы по времени, вы можете запускать его один раз в день и добавьте раздел следующего дня (на S3 не должно быть никаких данных, вы можете добавить разделы, которые еще не содержат данных, это просто метаданные). Если это более сложно, вы можете запустить функцию Lambda, когда новые файлы создаются на S3 и добавляют разделы в качестве реакции.

Это может звучать более сложно, чем при использовании Glue Crawler, и если бы Glue Crawlers действительно работали так, как вы ожидаете, это было бы. действительно работают очень хорошо, это будет намного меньше работы.

1 голос
/ 19 апреля 2020

Вы можете использовать попытку в качестве обходного пути для вашей проблемы.

    select col1, try(metadata.opt1) from "db-name".tablename
...