Как извлечь отдельные значения из GeoJSON в BigQuery

#sql #google-bigquery #gis #geojson

#sql #google-bigquery #гис #geojson

Вопрос:

У меня есть строка GeoJSON для многоточечной геометрии. Я хочу извлечь каждую из этих точек в таблицу геометрий отдельных точек в BigQuery

Мне удалось добиться точечной геометрии для одной из точек. Я хочу сделать это и для всех остальных в автоматическом режиме. Я уже пытался преобразовать строку в массив, но это остается массивом размером 1 со всем содержимым в виде одной строки.

У меня сработало то, что я смог извлечь одну точку и преобразовать ее в геометрию

 WITH temp_table as (select '{ "type": "MultiPoint", "coordinates": [ [ 20, 10 ], [ 30, 5 ], [ 90, 50 ], [ 40, 80 ] ]  }' as string) 

select ST_GEOGPOINT(CAST(JSON_EXTRACT(string, '$.coordinates[0][0]') as FLOAT64), CAST(JSON_EXTRACT(string, '$.coordinates[0][1]') as FLOAT64))  from temp_table
  

Это приводит к POINT(20 10)

Я могу написать запросы вручную для каждой из этих точек и выполнить UNION ALL но это не будет масштабироваться или работать каждый раз. Я хочу добиться этого таким образом, чтобы он мог выполнять это автоматизированным способом. Для архитектурных целей мы не можем выполнять манипуляции со строками в таких языках, как Python.

Ответ №1:

Ниже приведен стандартный SQL BigQuery

 #standardSQL
SELECT 
  ARRAY(
    SELECT ST_GEOGPOINT(
      CAST(SPLIT(pair)[OFFSET(0)] AS FLOAT64), CAST(SPLIT(pair)[SAFE_OFFSET(1)] AS FLOAT64)) 
    FROM UNNEST(REGEXP_EXTRACT_ALL(JSON_EXTRACT(STRING, '$.coordinates'), r'[(d ,d )]')) pair
  ) points
FROM `project.dataset.temp_table`  
  

Вы можете протестировать, поиграть с приведенным выше примером данных из вашего вопроса, как в примере ниже

 #standardSQL
WITH `project.dataset.temp_table` AS (
  SELECT '{ "type": "MultiPoint", "coordinates": [ [ 20, 10 ], [ 30, 5 ], [ 90, 50 ], [ 40, 80 ] ]  }' AS STRING
) 
SELECT 
  ARRAY(
    SELECT ST_GEOGPOINT(
      CAST(SPLIT(pair)[OFFSET(0)] AS FLOAT64), CAST(SPLIT(pair)[SAFE_OFFSET(1)] AS FLOAT64)) 
    FROM UNNEST(REGEXP_EXTRACT_ALL(JSON_EXTRACT(STRING, '$.coordinates'), r'[(d ,d )]')) pair
  ) points
FROM `project.dataset.temp_table`   
  

с результатом

 Row points   
1   POINT(20 10)     
    POINT(30 5)  
    POINT(90 50)     
    POINT(40 80)     
  

Примечание: в приведенной выше версии — массив точек создается для каждой соответствующей исходной строки. Очевидно, вы можете настроить его на выравнивание, как в примере ниже

 #standardSQL
WITH `project.dataset.temp_table` AS (
  SELECT '{ "type": "MultiPoint", "coordinates": [ [ 20, 10 ], [ 30, 5 ], [ 90, 50 ], [ 40, 80 ] ]  }' AS STRING
) 
SELECT 
  ST_GEOGPOINT(
      CAST(SPLIT(pair)[OFFSET(0)] AS FLOAT64), CAST(SPLIT(pair)[SAFE_OFFSET(1)] AS FLOAT64)
  ) points
FROM `project.dataset.temp_table`, UNNEST(REGEXP_EXTRACT_ALL(JSON_EXTRACT(STRING, '$.coordinates'), r'[(d ,d )]')) pair   
  

с результатом

 Row points   
1   POINT(20 10)     
2   POINT(30 5)  
3   POINT(90 50)     
4   POINT(40 80)