Как создать представление для таблицы с полями записи?
У нас есть еженедельный процесс резервного копирования, который экспортирует наше производственное хранилище Google Appengine Datastore в Google Cloud Storage, а затем в Google BigQuery. Каждую неделю мы создаем новый набор данных с именем как YYYY_MM_DD
который содержит копию производственных таблиц в этот день. Со временем мы собрали много наборов данных, таких как 2014_05_10
, 2014_05_17
и т. д. Я хочу создать набор данных Latest_Production_Data
который содержит представление для каждой из таблиц в самой последней YYYY_MM_DD
набор данных. Это облегчит для последующих отчетов один раз написать запрос и всегда получать самые последние данные.
Для этого у меня есть код, который получает самый последний набор данных и имена всех таблиц, которые набор данных содержит из API BigQuery. Затем для каждой из этих таблиц я запускаю вызов tables.insert, чтобы создать представление, которое является SELECT *
из таблицы, которую я ищу, чтобы создать ссылку на.
Это не работает для таблиц, которые содержат RECORD
поле, из того, что выглядит довольно милым правилом именования столбцов.
Например, у меня есть эта таблица:
Для которого я выпускаю этот вызов API:
{
'tableReference': {
'projectId': 'redacted',
'tableId': u'AccountDeletionRequest',
'datasetId': 'Latest_Production_Data'
}
'view': {
'query': u'SELECT * FROM [2014_05_17.AccountDeletionRequest]'
},
}
Это приводит к следующей ошибке:
HttpError: https://www.googleapis.com/bigquery/v2/projects//datasets/Latest_Production_Data/tables?alt=json вернул "Неверное имя поля"__key__. Namespace". Поля должны содержать только буквы, цифры и символы подчеркивания, начинаться с буквы или подчеркивания и содержать не более 128 символов.">
Когда я выполняю этот запрос в веб-консоли BigQuery, столбцы переименовываются для перевода .
для _
, Я ожидал, что то же самое произойдет, когда я выполню вызов API create view.
Есть ли простой способ, которым я могу программно создать представление для каждой из таблиц в моем наборе данных, независимо от их базовой схемы? Проблема, с которой я сталкиваюсь сейчас, касается столбцов записей, но я ожидаю еще одну проблему для таблиц с повторяющимися полями. Есть ли волшебная альтернатива SELECT *
что позаботится обо всех этих тонкостях для меня?
У меня была еще одна идея - сделать копию таблицы, но я бы предпочел не дублировать данные, если вообще смогу их избежать.
2 ответа
Вот обходной код, который я написал, чтобы динамически генерировать SELECT
утверждение для каждой из таблиц:
def get_leaf_column_selectors(dataset, table):
schema = table_service.get(
projectId=BQ_PROJECT_ID,
datasetId=dataset,
tableId=table
).execute()['schema']
return ",\n".join([
_get_leaf_selectors("", top_field)
for top_field in schema["fields"]
])
def _get_leaf_selectors(prefix, field):
if prefix:
format = prefix + ".%s"
else:
format = "%s"
if 'fields' not in field:
# Base case
actual_name = format % field["name"]
safe_name = actual_name.replace(".", "_")
return "%s as %s" % (actual_name, safe_name)
else:
# Recursive case
return ",\n".join([
_get_leaf_selectors(format % field["name"], sub_field)
for sub_field in field["fields"]
])
У нас была ошибка, из-за которой вам нужно было выбрать отдельные поля в представлении и использовать "как", чтобы переименовать поля во что-то допустимое (т. Е. У них нет "." В имени).
Ошибка исправлена, поэтому вы больше не должны видеть эту проблему. Пожалуйста, пропингуйте эту ветку или начните новый вопрос, если увидите его снова.