#node.js #google-bigquery
#node.js #google-bigquery
Вопрос:
Во-первых, простой BigQuery SQL:
Мы пытаемся взять следующий выполняемый SQL-запрос BigQuery и преобразовать его в параметризованный запрос для выполнения в Node.js:
SELECT * FROM UNNEST([
STRUCT(
ST_GEOGFROMTEXT('POINT(1 2)') AS lnglat,
TIMESTAMP('2020-01-01') AS stamp
)
])
Запрос просто создает псевдотаблицу из массива структур. В частности, типы выходных данных соответствуют ожидаемым, столбец stamp является TIMESTAMP
типом BigQuery и lnglat
является GEOGRAPHY
типом BigQuery.
Теперь давайте попробуем Node.js .
Давайте заменим массив структур BigQuery выше на @points
, и передадим массив объектных литералов JavaScript как params
:
// this is version 5.3.0
const { BigQuery, Geography } = require('@google-cloud/bigquery');
const bigquery = new BigQuery();
(async () => {
const query = 'SELECT * from UNNEST(@points)';
const params = { points: [
{
lnglat: new Geography('POINT(1 2)'),
stamp: BigQuery.timestamp('2020-01-01')
}
] };
const [job] = await bigquery.createQueryJob({ query, params });
// Wait for the query to finish
const [rows] = await job.getQueryResults();
// Print the results
console.log('Rows:');
console.log(rows);
})();
Возвращает следующий результат в моем CLI:
> node index.js
Rows:
[
{
lnglat: { value: 'POINT(1 2)' },
stamp: BigQueryTimestamp { value: '2020-01-01T00:00:00.000Z' }
}
]
Проблема в том, что, несмотря на NodeJS SDK, содержащий документы по «Географии» здесь, здесь и здесь, ни один из этих методов, похоже, фактически не заставляет BigQuery создавать собственный GEOGRAPHY
тип BigQuery внутри BigQuery.
Похоже, вместо этого BigQuery интерпретирует new Geography()
как RECORD
тип с value
полем, указанным в ответе выше, а также проверяется путем проверки временной (анонимной) таблицы, созданной в пользовательском интерфейсе BigQuery:
Мы пробовали разные варианты функций / классов географии: Geography
, BigQuery.Geography
, и bigquery.Geography
; все они возвращают один и тот же RECORD
тип.
Как ни странно, если вместо этого мы запрашиваем существующую таблицу (в отличие от построения псевдотаблицы во время выполнения), результат будет более соответствовать тому, что я ожидал:
Rows:
[ { lnglat: Geography { value: 'POINT(-118.43356046 45.97057312)' } } ]
Обратите внимание на Geography
тип в ответе!
Мы знаем, что мы можем отказаться от указания lnglat
в качестве строкового литерала JavaScript, и следующий SQL преобразует его в собственную ГЕОГРАФИЮ, обернув в CTE:
WITH points AS (
SELECT * from UNNEST(@points)
)
SELECT * EXCEPT(lnglat), ST_GEOGFROMTEXT(lnglat) AS lnglat FROM points
Но, к сожалению, мы хотим использовать эту псевдотаблицу в качестве фильтра для гораздо большей таблицы на диске, а использование этой CTE-оболочки исключает возможность для этого запроса (не проиллюстрированного здесь) использовать кластеризацию. Кластеризация очень важна для экономии средств и производительности выполнения. Я могу подробнее рассказать об этом, если вы попросите.
В конце концов, это все еще не объясняет, почему собственные географии не материализуются в псевдотаблице.
Вопрос:
Как мы можем использовать BigQuery NodeJS SDK для создания собственного GEOGRAPHY
типа BigQuery, аналогичного тому, что мы можем сделать с BigQuery.timestamp()
(выше), без CTE?
Комментарии:
1. Это ошибка в библиотеке. Я открыл исправление: github.com/googleapis/nodejs-bigquery/pull/877
2. приятно видеть, что это исправлено! спасибо @SteffanyBrown