Utilizzo dei dati geospaziali

L'analisi geospaziale ti consente di analizzare i dati geografici in BigQuery. I dati geografici sono noti anche come dati geospaziali.

I tipi comuni di oggetti quando si utilizzano i dati geospaziali includono:

  • Una geometria rappresenta un'area della superficie terrestre. Viene spesso descritto utilizzando punti, linee, poligoni o una raccolta di punti, linee e poligoni. Una raccolta di geometrie è una geometria che rappresenta l'unione spaziale di tutte le forme nella raccolta.
  • Una funzionalità spaziale rappresenta un oggetto spaziale logico. Combina una geometria con attributi aggiuntivi specifici dell'applicazione.
  • Una raccolta di funzionalità spaziali è un insieme di elementi spaziali.

In BigQuery, il tipo di dati GEOGRAPHY rappresenta un valore di geometria o una raccolta di geometria. Per rappresentare gli elementi spaziali, crea una tabella con una colonna GEOGRAPHY per la geometria e altre colonne per gli attributi. Ogni riga della tabella è una funzionalità spaziale e l'intera tabella rappresenta una raccolta di caratteristiche spaziali.

Il tipo di dati GEOGRAPHY descrive un insieme di punti sulla superficie del pianeta. Un insieme di punti è un insieme di punti, linee e poligoni sullo sferico di riferimento WGS84, con bordi geodesi. Puoi utilizzare il tipo di dati GEOGRAPHY chiamando una delle funzioni geografiche standard di SQL.

Caricamento di dati geospaziali

I singoli punti della Terra possono essere descritti solo da una coppia di longitudine, latitudine. Ad esempio, puoi caricare un file CSV che contiene i valori di longitudine e latitudine e poi utilizzare la funzione ST_GEOGPOINT per convertirli in valori GEOGRAPHY.

Per aree geografiche più complesse, puoi caricare i seguenti formati di dati geospaziali in una colonna GEOGRAPHY:

  • Testo noto (WKT)
  • Programma binario noto (WKB)
  • GeoJSON

Caricamento di dati WKT o WKB

WKT è un formato di testo per la descrizione delle singole forme geometriche tramite punti, linee, poligoni con fori facoltativi o una raccolta di punti, linee o poligoni. WKB è la versione binaria del formato WKT. WKB può essere con codifica esadecimale per i formati che non supportano i dati binari, come JSON.

Ad esempio, quanto segue definisce un punto in WKT:

POINT(-121 41)

Per descrivere una funzionalità spaziale, il WKT è generalmente incorporato in un formato di file container, ad esempio un file CSV, o in una tabella di database. Una riga del file o una riga della tabella corrisponde di solito alla funzionalità spaziale. L'intero file o l'intera tabella corrispondono alla raccolta di funzionalità. Per caricare i dati WKT in BigQuery, fornisci uno schema che specifichi una colonna GEOGRAPHY per i dati geospaziali.

Ad esempio, potresti avere un file CSV contenente i seguenti dati:

"POLYGON((-124.49 47.35,-124.49 40.73,-116.49 40.73,-116.49 47.35,-124.49 47.35))",poly1
"POLYGON((-85.6 31.66,-85.6 24.29,-78.22 24.29,-78.22 31.66,-85.6 31.66))",poly2
"POINT(1 2)",point1

Puoi caricare questo file eseguendo il comando load dello strumento a riga di comando bq:

bq load --source_format=CSV \
  --schema="geography:GEOGRAPHY,name:STRING" \
  mydataset.mytable filename1.csv

Per ulteriori informazioni sul caricamento dei dati in BigQuery, consulta Introduzione al caricamento dei dati.

Per trasmettere in streaming i dati WKT a una tabella BigQuery esistente con una colonna GEOGRAPHY, serializza i dati come stringa nella richiesta API.

bq

Esegui lo comando bq dello strumento a riga di comando insert:

echo '{"geo": "LINESTRING (-118.4085 33.9416, -73.7781 40.6413)"}' \
    | bq insert my_dataset.geo_table

Python

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Python per BigQuery.

from google.cloud import bigquery
import shapely.geometry
import shapely.wkt

bigquery_client = bigquery.Client()

# This example uses a table containing a column named "geo" with the
# GEOGRAPHY data type.
table_id = "my-project.my_dataset.my_table"

# Use the Shapely library to generate WKT of a line from LAX to
# JFK airports. Alternatively, you may define WKT data directly.
my_geography = shapely.geometry.LineString(
    [(-118.4085, 33.9416), (-73.7781, 40.6413)]
)
rows = [
    # Convert data into a WKT string.
    {"geo": shapely.wkt.dumps(my_geography)},
]

#  table already exists and has a column
# named "geo" with data type GEOGRAPHY.
errors = bigquery_client.insert_rows_json(table_id, rows)
if errors:
    raise RuntimeError(f"row insert failed: {errors}")
else:
    print(f"wrote 1 row to {table_id}")

Per ulteriori informazioni sul flusso di dati in BigQuery, consulta la pagina relativa ai flussi di dati in BigQuery.

Puoi anche convertire una stringa di testo WKT in un valore GEOGRAPHY utilizzando la funzione ST_GeogFromText.

Caricamento di dati GeoJSON

GeoJSON è un formato basato su JSON per geometrie e caratteristiche spaziali. Ad esempio, quanto segue definisce un punto in GeoJSON:

{ "type": "Point", "coordinates": [-121,41] }

I dati GeoJSON possono contenere uno dei seguenti tipi di oggetti:

  • Oggetti geometrici. Un oggetto geometrico è una forma spaziale, descritta come punto di unione di punti, linee e poligoni con fori facoltativi.
  • Oggetti in primo piano. Un oggetto caratteristica contiene una geometria più ulteriori coppie nome/valore, il cui significato è specifico dell'applicazione.
  • Raccolte di funzionalità. Una raccolta di caratteristiche è un insieme di oggetti caratteristica.

Esistono due modi per caricare i dati GeoJSON in BigQuery:

Caricamento di file GeoJSON delimitati da nuova riga

Un file GeoJSON delimitato da nuova riga contiene un elenco di oggetti delle funzionalità GeoJSON, uno per riga nel file. Un oggetto funzionalità GeoJSON è un oggetto JSON con i seguenti membri:

  • type. Per gli oggetti caratteristica, il valore deve essere Feature. BigQuery convalida il valore, ma non lo include nello schema della tabella.

  • geometry. Il valore è un oggetto GeoJSON Geometry o null. BigQuery converte questo membro in un valore GEOGRAPHY.

  • properties. Il valore è qualsiasi oggetto JSON o null. Se il valore non è null, BigQuery carica ogni membro dell'oggetto JSON come colonna di tabella separata. Per ulteriori informazioni su come BigQuery analizza i tipi di dati JSON, consulta Dettagli sul caricamento dei dati JSON.

  • id. Facoltativo. Se presente, il valore è una stringa o un numero. BigQuery carica questo valore in una colonna denominata id.

Se l'oggetto funzionalità contiene altri membri che non sono elencati qui, BigQuery li converte direttamente in colonne della tabella.

Puoi caricare un file GeoJSON delimitato da nuova riga utilizzando il comando bq load dello strumento a riga di comando bq, come indicato di seguito:

bq load \
 --source_format=NEWLINE_DELIMITED_JSON \
 --json_extension=GEOJSON \
 --autodetect \
 DATASET.TABLE \
 FILE_PATH_OR_URI

Sostituisci quanto segue:

  • DATASET è il nome del tuo set di dati.
  • TABLE è il nome della tabella di destinazione.
  • FILE_PATH_OR_URI è un percorso a un file locale o a un URI Cloud Storage.

L'esempio precedente abilita il rilevamento automatico degli schemi. Per un maggiore controllo su come BigQuery converte i valori all'interno dell'oggetto properties, puoi fornire uno schema esplicito. Per ulteriori informazioni, consulta la sezione Specificare manualmente gli schemi. Se fornisci uno schema esplicito, non includere una colonna type di primo livello nella definizione dello schema. Per ogni membro del membro properties, definisci colonne separate, non una singola colonna nidificata.

Secondo RFC 7946, una struttura di dati GeoJSON completa è un singolo oggetto JSON. Molti sistemi esportano dati GeoJSON come un singolo oggetto FeatureCollection che contiene tutte le geometrie. Per caricare questo formato in BigQuery, devi convertire il file rimuovendo l'oggetto FeatureCollection a livello principale e dividendo i singoli oggetti delle funzionalità in righe separate. Ad esempio, il seguente comando utilizza lo strumento a riga di comando jq per suddividere un file GeoJSON in un formato delimitato da nuova riga:

cat ~/file1.json | jq -c '.features[]' > converted.json

Creazione di una tabella esterna da un file GeoJSON delimitato da nuova riga

Puoi eseguire query su un file GeoJSON delimitato da nuova riga archiviato in Cloud Storage creando una tabella esterna. Per creare la tabella esterna, utilizza l'istruzione DDL CREATE EXTERNAL TABLE. Nella clausola OPTIONS, imposta l'opzione format su NEWLINE_DELIMITED_JSON e l'opzione json_extension su GEOJSON.

Esempio:

CREATE EXTERNAL TABLE mydataset.table1 OPTIONS (
  format="NEWLINE_DELIMITED_JSON",
  json_extension = 'GEOJSON',
  uris = ['gs://mybucket/geofile.json']
);

Caricamento di dati geometrici GeoJSON

L'analisi geospaziale supporta il caricamento di singoli oggetti della geometria GeoJSON incorporati come stringhe di testo in altri tipi di file. Ad esempio, puoi caricare un file CSV in cui una delle colonne contiene un oggetto di geometria GeoJSON.

Per caricare questo tipo di dati GeoJSON in BigQuery, fornisci uno schema che specifichi una colonna GEOGRAPHY per i dati GeoJSON. Devi fornire manualmente lo schema. In caso contrario, se viene attivato il rilevamento automatico, BigQuery carica i dati come valore STRING.

L'analisi geospaziale non supporta il caricamento di oggetti o raccolte di caratteristiche GeoJSON tramite questo approccio. Se devi caricare oggetti caratteristica, valuta l'utilizzo di file GeoJSON delimitati da una nuova riga.

Per includere flussi di dati GeoJSON in una tabella BigQuery esistente con una colonna GEOGRAPHY, serializza i dati come stringa nella richiesta API.

bq

Esegui lo comando bq dello strumento a riga di comando insert:

echo '{"geo": "{\"type\": \"LineString\", \"coordinates\": [[-118.4085, 33.9416], [-73.7781, 40.6413]]}"}' \
  | bq insert my_dataset.geo_table

Python

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Python per BigQuery.

import geojson
from google.cloud import bigquery

bigquery_client = bigquery.Client()

# This example uses a table containing a column named "geo" with the
# GEOGRAPHY data type.
table_id = "my-project.my_dataset.my_table"

# Use the python-geojson library to generate GeoJSON of a line from LAX to
# JFK airports. Alternatively, you may define GeoJSON data directly, but it
# must be converted to a string before loading it into BigQuery.
my_geography = geojson.LineString([(-118.4085, 33.9416), (-73.7781, 40.6413)])
rows = [
    # Convert GeoJSON data into a string.
    {"geo": geojson.dumps(my_geography)}
]

#  table already exists and has a column
# named "geo" with data type GEOGRAPHY.
errors = bigquery_client.insert_rows_json(table_id, rows)
if errors:
    raise RuntimeError(f"row insert failed: {errors}")
else:
    print(f"wrote 1 row to {table_id}")

Puoi anche convertire un oggetto geometrico GeoJSON in un valore GEOGRAPHY utilizzando la funzione ST_GEOGFROMGEOJSON. Ad esempio, puoi archiviare le geometrie come valori STRING e poi eseguire una query che chiama ST_GEOGFROMGEOJSON.

Coordina sistemi e bordi

Nell'analisi geospaziale, i punti sono posizioni sulla superficie di uno sferoide WGS84, espressi come longitudine e latitudine geodetica. Un perimetro è una geodetica sferica tra due endpoint. Ciò significa che i bordi sono il percorso più breve sulla superficie di una sfera.

Il formato WKT non fornisce un sistema di coordinate. Quando si caricano i dati WKT, l'analisi geospaziale presuppone che i dati utilizzino le coordinate WGS84 con bordi sferici. Assicurati che i tuoi dati di origine corrispondano a quelli del sistema di coordinate, a meno che le aree geografiche non siano abbastanza piccole da poter ignorare la differenza tra gli angoli sferici e quelli planari.

GeoJSON utilizza esplicitamente le coordinate WGS84 con bordi planari. Quando si caricano i dati GeoJSON, l'analisi geospaziale converte i bordi planari in bordi sferici. L'analisi geospaziale aggiunge ulteriori punti alla linea, se necessario, in modo che la sequenza di bordi convertita rimanga entro 10 metri dalla linea originale. Questo processo è noto come tessellation o densificazione non uniforme. Non puoi controllare direttamente il processo di vendita.

Per caricare aree geografiche con bordi sferici, utilizza WKT. Per caricare aree geografiche con bordi planari, spesso chiamati geometrie, è più facile utilizzare GeoJSON. Tuttavia, se i dati di geometria sono già in formato WKT, un'altra opzione consiste nel caricare i dati come tipo STRING e utilizzare la funzione ST_GEOGFROMTEXT per convertire i valori in GEOGRAPHY. Imposta il parametro planar su TRUE per interpretare i dati come planari.

Quando scegli un formato di interscambio, assicurati di comprendere il sistema di coordinate utilizzato dai dati di origine. La maggior parte dei sistemi supporta esplicitamente l'analisi della geografia (anziché la geometria) da WKT, altrimenti presuppongono bordi planari.

Le coordinate devono essere prima la longitudine, la seconda latitudine. Se l'area geografica presenta segmenti o bordi lunghi, questi devono essere ssellati, perché l'analisi geospaziale li interpreta come geodetiche sferiche, che potrebbero non corrispondere al sistema di coordinate in cui hanno avuto origine i dati.

Orientamento poligono

Su una sfera, ogni poligono ha un poligono complementare. Ad esempio, un poligono che descrive i continenti della Terra avrà un poligono complementare che descrive gli oceani della Terra. Poiché i due poligoni sono descritti dagli stessi anelli di confine, sono necessarie delle regole per risolvere l'ambiguità attorno alla quale vengono descritti da una determinata stringa WKT.

Quando carichi stringhe WKT e WKB da file o utilizzando l'importazione dei flussi di dati, l'analisi geospaziale presuppone che i poligoni nell'input siano orientati come segue: Se trascini il confine del poligono nell'ordine dei vertici di input, l'interno del poligono si trova a sinistra. L'analisi geospaziale utilizza la stessa regola quando si esportano oggetti geografici in stringhe WKT e WKB.

Se utilizzi la funzione ST_GeogFromText per convertire una stringa WKT in un valore GEOGRAPHY, il parametro oriented specifica in che modo la funzione determina il poligono:

  • FALSE: interpreta l'input come poligono con l'area più piccola. Questo è il comportamento predefinito.

  • TRUE: utilizza la regola di orientamento a sinistra descritta in precedenza. Questa opzione consente di caricare poligoni con un'area più grande di un emisfero.

Poiché le stringhe GeoJSON sono definite su una mappa planare, l'orientamento può essere determinato senza ambiguità, anche se l'input non segue la regola di orientamento definita nella specifica del formato GeoJSON, RFC 7946.

Gestione dei dati spaziali non correttamente formattati

Quando carichi dati spaziali provenienti da altri strumenti in BigQuery, potresti riscontrare errori di conversione dovuti a dati WKT o GeoJSON non validi. Ad esempio, un errore come Edge K has duplicate vertex with edge N indica che il poligono ha vertici duplicati (oltre al primo e all'ultimo).

Per evitare problemi di formattazione, puoi utilizzare una funzione che genera un output conforme agli standard. Ad esempio, quando esporti dati da PostGIS, puoi utilizzare la funzione ST_MakeValid PostGIS per standardizzare l'output. In alternativa, puoi importare i dati come testo e convertirli chiamando ST_GEOGFROMTEXT o ST_GEOGFROMGEOJSON con il parametro make_valid. Quando make_valid è TRUE, queste funzioni tentano di riparare i poligoni non validi.

Per trovare o ignorare i dati con formattazione errata, utilizza il prefisso della funzione SAFE per generare i dati problematici. Ad esempio, la seguente query usa il prefisso SAFE per recuperare i dati spaziali non correttamente formattati.

SELECT
  geojson AS bad_geojson
FROM
  mytable
WHERE
  geojson IS NOT NULL
  AND SAFE.ST_GeogFromGeoJson(geojson) IS NULL

Vincoli

L'analisi geospaziale non supporta le seguenti funzionalità nei formati geospaziali:

  • Geometrie tridimensionali. Sono inclusi il suffisso "Z" nel formato WKT e la coordinata di altitudine nel formato GeoJSON.
  • Sistemi di riferimento lineare. Questo include il suffisso "M" in formato WKT.
  • Oggetti di geometria WKT diversi dalle primitive di geometria o dalle geometrie multiparte. In particolare, l'analisi geospaziale supporta solo Point, MultiPoint, LineString, MultiLineString, poligoni, Multi poligoni e GeometryCollection.

Per i vincoli specifici dei formati di input GeoJson e WKT, consulta ST_GeogFromGeoJson e ST_GeogFromText.

Trasformazione dei dati geospaziali

Se la tua tabella contiene colonne separate per longitudine e latitudine, puoi trasformare i valori in aree geografiche utilizzando le funzioni geografiche standard di SQL come ST_GeogPoint. Ad esempio, se hai due colonne DOUBLE per longitudine e latitudine, puoi creare una colonna di area geografica con la seguente query:

SELECT
  *,
  ST_GeogPoint(longitude, latitude) AS g
FROM
  mytable

BigQuery può convertire stringhe WKT e GeoJSON in tipi geografici. Se i dati sono in un altro formato, ad esempio Shapefiles, utilizza uno strumento esterno per convertirli in un formato di file di input supportato, ad esempio un file CSV, con le colonne GEOGRAPHY codificate come stringhe WKT o GeoJSON.

Partizionamento e clustering dei dati geospaziali

Puoi eseguire il partizionamento e le tabelle di cluster contenenti GEOGRAPHY colonne. Puoi utilizzare una colonna GEOGRAPHY come colonna di clustering, ma non puoi utilizzare una colonna GEOGRAPHY come colonna di partizionamento.

Se archivi i dati di GEOGRAPHY in una tabella e le query filtrano i dati utilizzando un predicato spaziale, assicurati che il cluster sia raggruppati in base alla colonna GEOGRAPHY. Ciò consente di migliorare le prestazioni delle query e potrebbe ridurre i costi. Un predicato spaziale chiama una funzione geografica booleana e ha una colonna GEOGRAPHY come uno degli argomenti. L'esempio seguente mostra un predicato spaziale che utilizza la funzione ST_DWithin:

WHERE ST_DWithin(geo, ST_GeogPoint(longitude, latitude), 100)

Utilizzo di JOIN con i dati spaziali

I JOIN di entità spaziale sono unioni di due tabelle con una funzione geografica predicata nella clausola WHERE. Ad esempio:

-- how many stations within 1 mile range of each zip code?
SELECT
    zip_code AS zip,
    ANY_VALUE(zip_code_geom) AS polygon,
    COUNT(*) AS bike_stations
FROM
    `bigquery-public-data.new_york.citibike_stations` AS bike_stations,
    `bigquery-public-data.geo_us_boundaries.zip_codes` AS zip_codes
WHERE ST_DWithin(
         zip_codes.zip_code_geom,
         ST_GeogPoint(bike_stations.longitude, bike_stations.latitude),
         1609.34)
GROUP BY zip
ORDER BY bike_stations DESC

I join spaziali hanno un rendimento migliore quando i dati geografici sono persistenti. L'esempio precedente crea i valori geografici nella query. È più efficiente archiviare i valori geografici in una tabella BigQuery.

Ad esempio, la seguente query recupera le coppie di longitudine, latitudine e convertirle in punti geografici. Quando esegui questa query, specifichi una nuova tabella di destinazione in cui archiviare i risultati della query:

SELECT
  *,
  ST_GeogPoint(pLongitude, pLatitude) AS p
FROM
  mytable

BigQuery implementa JOIN per lo spazio ottimizzato per gli operatori INNER JOIN e CROSS JOIN con le seguenti funzioni di predicato SQL standard:

I join spaziali non sono ottimizzati:

  • Per i join a SINISTRA, DESTRA o FULL OUTER
  • Nei casi che prevedono il join ANTI
  • Quando viene negato il predicato spaziale

Un JOIN che utilizza il predicato ST_DWithin è ottimizzato solo quando il parametro della distanza è un'espressione costante.

Esportazione dei dati spaziali

Quando esporti dati spaziali da BigQuery, i valori delle colonne GEOGRAPHY sono sempre formattati come stringhe WKT. Per esportare i dati in formato GeoJSON, utilizza la funzione ST_AsGeoJSON.

Se gli strumenti che stai utilizzando per analizzare i dati esportati non comprendono il tipo di dati GEOGRAPHY, puoi convertire i valori delle colonne in stringhe utilizzando una funzione geografica come ST_AsText o ST_AsGeoJSON. L'analisi geospaziale aggiunge ulteriori punti alla linea, ove necessario, in modo che la sequenza di bordi convertita rimanga entro 10 metri dalla linea geodetica originale.

Ad esempio, la seguente query utilizza ST_AsGeoJSON per convertire i valori GeoJSON in stringhe.

SELECT
  ST_AsGeoJSON(ST_MakeLine(ST_GeogPoint(1,1), ST_GeogPoint(3,2)))

I dati risultanti sarebbero simili ai seguenti:

{ "type": "LineString", "coordinates": [ [1, 1], [1.99977145571783, 1.50022838764041], [2.49981908082299, 1.75018082434274], [3, 2] ] }

La linea GeoJSON presenta due punti aggiuntivi. L'analisi geospaziale aggiunge questi punti in modo che la linea GeoJSON segua da vicino lo stesso percorso sul campo della linea originale.

Passaggi successivi