Сначала немного фона:
Я создал 2 таблицы под сбором данных test
следующим образом:
1
Схема: имя (строка), возраст (целое число)
"Varun", 19
"Raja", 27
2
Схема pet_name (String), тип (String)
"jimmy", "dog"
"ramesh", "cat"
Обратите внимание, что эти два отношения имеют разные схемы.
Здесь я копирую содержимое таблицы данных 2
в 1
. bigquery.WriteAppend
указывает обработчику запросов добавить результаты таблицы 2
в 1
.
test := client.Dataset("test")
copier := test.Table("1").CopierFrom(test.Table("2"))
copier.WriteDisposition = bigquery.WriteAppend
if _, err := copier.Run(ctx); err != nil {
log.Fatalln(err)
}
query := client.Query("SELECT * FROM `test.1`;")
results, err := query.Read(ctx)
if err != nil {
log.Fatalln(err)
}
for {
row := make(map[string]bigquery.Value)
err := results.Next(&row)
if err == iterator.Done {
return
}
if err != nil {
log.Fatalln(err)
}
fmt.Println(row)
}
Ничего не происходит и результат:
map[age:19 name:Varun]
map[name:Raja age:27]
Таблица 1
, пункт назначения не изменился.
Что если в копии источника и получателя указаны одинаковые схемы?
Например:
copier := test.Table("1").CopierFrom(test.Table("1"))
Тогда копия удалась! Добавить таблицу 1
имеет в два раза больше строк, чем изначально.
map[name:Varun age:19]
map[age:27 name:Raja]
map[name:Varun age:19]
map[name:Raja age:27]
Но что, если мы как-то захотим объединить таблицы даже с различными схемами ?
Во-первых, вам нужна учетная запись GCP, поскольку вы технически выполняете манипуляции с данными (DML). Вы можете получить бесплатный кредит в размере 300 долларов США.
Тогда будет работать следующее
query := client.Query("SELECT * FROM `test.2`;")
query.SchemaUpdateOptions = []string{"ALLOW_FIELD_ADDITION", "ALLOW_FIELD_RELAXATION"}
query.CreateDisposition = bigquery.CreateIfNeeded
query.WriteDisposition = bigquery.WriteAppend
query.QueryConfig.Dst = client.Dataset("test").Table("1")
results, err := query.Read(ctx)
И результат
map[pet_name:<nil> type:<nil> name:Varun age:19]
map[name:Raja age:27 pet_name:<nil> type:<nil>]
map[pet_name:ramesh type:cat name:<nil> age:<nil>]
map[pet_name:jimmy type:dog name:<nil> age:<nil>]
EDIT
Вместо query.Read()
вы можете использовать query.Run()
, если вы просто хотите выполнить запрос и не получать результаты обратно, как показано ниже:
if _, err := query.Run(ctx); err != nil {
log.Fatalln(err)
}
Важные вещи, на которые стоит обратить внимание:
- Мы установили
query.SchemaUpdateOptions
для включения ALLOW_FIELD_ADDITION
, что позволит результирующей таблице иметь столбцы, которые изначально не присутствовали.
- Мы установили
query.WriteDisposition
на bigquery.WriteAppend
для данных, которые будут добавлены.
- Мы установили
query.QueryConfig.Dst
в client.Dataset("test").Table("1")
, что означает, что результат запроса будет загружен в 1
.
- Значения, которые находятся не в обеих таблицах, а только в одной, обнуляются или имеют значение
nil
в смысле Голанга.
Этот хак даст вам те же результаты, что и объединение двух таблиц.
Надеюсь, это поможет.