1. Übersicht
Karten können ein sehr leistungsstarkes Tool sein, um Muster in einem Dataset zu visualisieren, die in irgendeiner Weise mit dem Standort zusammenhängen. Diese Beziehung kann der Name eines Orts, ein bestimmter Breiten- und Längengrad oder der Name eines Gebiets mit einer bestimmten Grenze sein, z. B. ein Zensusbezirk oder eine Postleitzahl.
Wenn diese Datasets sehr groß werden, können sie mit herkömmlichen Tools nur schwer abgefragt und visualisiert werden. Wenn Sie Google BigQuery zum Abfragen der Daten und die Google Maps APIs zum Erstellen der Abfrage und Visualisieren der Ausgabe verwenden, können Sie geografische Muster in Ihren Daten schnell und mit sehr wenig Einrichtung oder Programmierung untersuchen. Außerdem müssen Sie kein System zum Speichern sehr großer Datasets verwalten.
Aufgaben
In diesem Codelab schreiben und führen Sie einige Abfragen aus, die zeigen, wie Sie mit BigQuery standortbezogene Statistiken aus sehr großen öffentlichen Datasets abrufen können. Außerdem erstellen Sie eine Webseite, auf der eine Karte mit der Google Maps Platform JavaScript API geladen wird. Anschließend führen Sie räumliche Abfragen für dieselben sehr großen öffentlichen Datasets aus und visualisieren sie mit der Google APIs Client Library for Javascript und der BigQuery API.
Lerninhalte
- BigQuery bietet die Möglichkeit, standortbezogene Datasets im Petabyte-Bereich in Sekundenschnelle abzufragen. Dazu werden SQL-Abfragen, benutzerdefinierte Funktionen und die BigQuery API verwendet.
- So fügen Sie mit der Google Maps Platform eine Google-Karte auf einer Webseite ein und ermöglichen Nutzern, Formen darauf zu zeichnen
- So visualisieren Sie Abfragen für große Datasets auf einer Google-Karte, wie im Beispielbild unten. Dort ist die Dichte der Taxistandorte im Jahr 2016 für Fahrten zu sehen, die im Block um das Empire State Building begonnen haben.
Voraussetzungen
- Grundkenntnisse in HTML, CSS, JavaScript, SQL und den Chrome-Entwicklertools
- Ein moderner Webbrowser, z. B. die aktuellen Versionen von Chrome, Firefox, Safari oder Edge.
- Ein Texteditor oder eine IDE Ihrer Wahl
Die Technologie
BigQuery
BigQuery ist der Datenanalysedienst von Google für sehr große Datasets. Sie hat eine RESTful API und unterstützt in SQL geschriebene Abfragen. Wenn Sie Daten mit Breiten- und Längengradwerten haben, können Sie Ihre Daten nach Standort abfragen. Der Vorteil ist, dass Sie sehr große Datasets visuell untersuchen können, um Muster zu erkennen, ohne Server- oder Datenbankinfrastruktur verwalten zu müssen. Dank der enormen Skalierbarkeit und der verwalteten Infrastruktur von BigQuery erhalten Sie in wenigen Sekunden Antworten auf Ihre Fragen, unabhängig davon, wie groß Ihre Tabellen werden.
Google Maps Platform
Die Google Maps Platform bietet programmatischen Zugriff auf die Karten-, Orts- und Routendaten von Google. Derzeit wird sie von über 2 Millionen Websites und Apps verwendet, um Nutzern eingebettete Karten und standortbezogene Anfragen zu ermöglichen.
Mit der Google Maps Platform Javascript API Drawing Layer können Sie Formen auf der Karte zeichnen. Diese können in Eingaben umgewandelt werden, um Abfragen für BigQuery-Tabellen auszuführen, in denen Breiten- und Längengradwerte in Spalten gespeichert sind.
Für den Einstieg benötigen Sie ein Google Cloud Platform-Projekt mit aktivierten BigQuery- und Maps-APIs.
2. Einrichtung
Google-Konto
Wenn Sie noch kein Google-Konto (Gmail oder Google Apps) haben, müssen Sie eines erstellen.
Projekt erstellen
Melden Sie sich in der Google Cloud Console ( console.cloud.google.com) an und erstellen Sie ein neues Projekt. Oben auf dem Bildschirm befindet sich ein Drop-down-Menü für Projekte:
Wenn Sie auf dieses Drop-down-Menü klicken, wird ein Menüelement angezeigt, mit dem Sie ein neues Projekt erstellen können:
Geben Sie in das Feld „Geben Sie einen neuen Namen für Ihr Projekt ein“ einen Namen für Ihr neues Projekt ein, z. B. „BigQuery Codelab“:
Eine Projekt-ID wird für Sie generiert. Die Projekt-ID ist für alle Google Cloud-Projekte ein eindeutiger Name. Merken Sie sich Ihre Projekt-ID, da Sie sie später benötigen. Der Name oben ist bereits vergeben und kann nicht verwendet werden. Ersetzen Sie YOUR_PROJECT_ID in diesem Codelab durch Ihre eigene Projekt-ID.
Abrechnung aktivieren
Melden Sie sich für BigQuery mit dem im vorherigen Schritt ausgewählten oder erstellten Projekt an. Die Abrechnung muss für dieses Projekt aktiviert sein. Nachdem die Abrechnung aktiviert wurde, können Sie die BigQuery API aktivieren.
Wie die Abrechnung aktiviert wird, hängt davon ab, ob Sie ein neues Projekt erstellen oder die Abrechnung für ein vorhandenes Projekt wieder aktivieren.
Google bietet einen 12-monatigen kostenlosen Testzeitraum für die Nutzung der Google Cloud Platform im Wert von bis zu 300 $. Möglicherweise können Sie diesen für dieses Codelab nutzen. Weitere Informationen finden Sie unter https://cloud.google.com/free/.
Neue Projekte
Wenn Sie ein neues Projekt erstellen, werden Sie aufgefordert, eines Ihrer Rechnungskonten auszuwählen, das Sie mit dem Projekt verknüpfen möchten. Wenn Sie nur ein Rechnungskonto haben, wird dieses Konto automatisch mit Ihrem Projekt verknüpft.
Wenn Sie kein Rechnungskonto haben, müssen Sie eines erstellen und die Abrechnung für Ihr Projekt aktivieren, damit Sie viele Google Cloud-Funktionen nutzen können. Wenn Sie ein neues Rechnungskonto erstellen und die Abrechnung für Ihr Projekt aktivieren möchten, folgen Sie der Anleitung unter Rechnungskonto erstellen, ändern oder schließen.
Vorhandene Projekte
Wenn Sie die Abrechnung für ein Projekt vorübergehend deaktiviert haben, können Sie sie wieder aktivieren:
- Rufen Sie die Cloud Platform Console auf.
- Wählen Sie in der Projektliste das Projekt aus, für das die Abrechnung wieder aktiviert werden soll.
- Öffnen Sie das Menü links in der Konsole und wählen Sie Abrechnung
aus. Sie werden aufgefordert, ein Rechnungskonto auszuwählen.
- Klicken Sie auf Konto festlegen.
Neues Rechnungskonto erstellen
So erstellen Sie ein neues Rechnungskonto:
- Rufen Sie die Cloud Platform Console auf und melden Sie sich an. Wenn Sie noch kein Konto haben, erstellen Sie eins.
- Öffnen Sie das Menü links in der Konsole und wählen Sie Abrechnung
aus.
- Klicken Sie auf Neues Rechnungskonto. Wenn dies nicht Ihr erstes Rechnungskonto ist, müssen Sie zuerst die Rechnungskontoliste öffnen. Klicken Sie dazu oben auf der Seite auf den Namen Ihres bestehenden Rechnungskontos und dann auf Rechnungskonten verwalten.
- Geben Sie den Namen des Rechnungskontos und die Abrechnungsinformationen ein. Welche Optionen angezeigt werden, hängt davon ab, in welchem Land sich die eingegebene Rechnungsadresse befindet. Beachten Sie, dass Sie bei Konten in den USA den Steuerstatus nicht ändern können, nachdem das Konto erstellt wurde.
- Klicken Sie auf Senden und Abrechnung aktivieren.
Standardmäßig ist der Ersteller des Rechnungskontos auch ein Abrechnungsadministrator des Kontos.
Informationen zum Bestätigen von Bankkonten und zum Hinzufügen von Sicherungsmethoden für die Zahlung finden Sie unter Zahlungsmethode hinzufügen, entfernen oder aktualisieren.
Aktivieren der BigQuery-API
Wenn Sie die BigQuery API in Ihrem Projekt aktivieren möchten, rufen Sie in der Console den Marketplace für die BigQuery API auf und klicken Sie auf die blaue Schaltfläche „Aktivieren“.
3. Standortdaten in BigQuery abfragen
Es gibt drei Möglichkeiten, Standortdaten abzufragen, die als Breiten- und Längengradwerte in BigQuery gespeichert sind.
- Rechteckabfragen: Geben Sie den interessierenden Bereich als Abfrage an, mit der alle Zeilen innerhalb eines minimalen und maximalen Breiten- und Längengradbereichs ausgewählt werden.
- Radiusabfragen: Sie geben den relevanten Bereich an, indem Sie einen Kreis um einen Punkt berechnen. Dazu verwenden Sie die Haversine-Formel und mathematische Funktionen, um die Form der Erde zu modellieren.
- Polygonabfragen: Geben Sie eine benutzerdefinierte Form an und verwenden Sie eine benutzerdefinierte Funktion, um die Logik für die Punkt-im-Polygon-Abfrage auszudrücken, die erforderlich ist, um zu prüfen, ob der Breiten- und Längengrad jeder Zeile innerhalb der Form liegt.
Verwenden Sie zum Einstieg den Abfrageeditor im BigQuery-Bereich der Google Cloud Console, um die folgenden Abfragen für die NYC-Taxidaten auszuführen.
Standard-SQL im Vergleich zu Legacy-SQL
BigQuery unterstützt zwei SQL-Versionen: Legacy-SQL und Standard-SQL. Letzteres ist der ANSI-Standard von 2011. In dieser Anleitung verwenden wir Standard-SQL, da es besser den Standards entspricht.
Wenn Sie Legacy-SQL im BigQuery-Editor ausführen möchten, gehen Sie so vor:
- Klicken Sie auf die Schaltfläche „Mehr“.
- Wählen Sie im Drop-down-Menü die Option „Abfrageeinstellungen“ aus.
- Wählen Sie unter „SQL-Dialekt“ das Optionsfeld „Legacy“ aus.
- Klicken Sie auf die Schaltfläche „Speichern“.
Rechteckabfragen
Rechteckabfragen lassen sich in BigQuery ganz einfach erstellen. Sie müssen nur eine WHERE
-Klausel hinzufügen, die die zurückgegebenen Ergebnisse auf Orte mit Breiten- und Längengraden zwischen den Mindest- und Höchstwerten beschränkt.
Probieren Sie das folgende Beispiel in der BigQuery-Konsole aus. Mit dieser Abfrage werden einige durchschnittliche Fahrtenstatistiken für Fahrten abgerufen, die in einem rechteckigen Bereich begonnen haben, der Midtown und Lower Manhattan umfasst. Sie können zwei verschiedene Standorte ausprobieren. Entfernen Sie die Auskommentierung der zweiten WHERE
-Klausel, um die Abfrage für Fahrten auszuführen, die am Flughafen JFK begonnen haben.
SELECT
ROUND(AVG(tip_amount),2) as avg_tip,
ROUND(AVG(fare_amount),2) as avg_fare,
ROUND(AVG(trip_distance),2) as avg_distance,
ROUND(AVG(tip_proportion),2) as avg_tip_pc,
ROUND(AVG(fare_per_mile),2) as avg_fare_mile FROM
(SELECT
pickup_latitude, pickup_longitude, tip_amount, fare_amount, trip_distance, (tip_amount / fare_amount)*100.0 as tip_proportion, fare_amount / trip_distance as fare_per_mile
FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2015`
WHERE trip_distance > 0.01 AND fare_amount <100 AND payment_type = "1" AND fare_amount > 0
)
--Manhattan
WHERE pickup_latitude < 40.7679 AND pickup_latitude > 40.7000 AND pickup_longitude < -73.97 and pickup_longitude > -74.01
--JFK
--WHERE pickup_latitude < 40.654626 AND pickup_latitude > 40.639547 AND pickup_longitude < -73.771497 and pickup_longitude > -73.793755
Die Ergebnisse der beiden Abfragen zeigen, dass es große Unterschiede bei der durchschnittlichen Fahrtstrecke, dem Fahrpreis und dem Trinkgeld für Abholungen an den beiden Standorten gibt.
Manhattan
avg_tip | avg_fare | avg_distance | avg_tip_pc | avg_fare_mile |
2,52 | 12.03 | 9,97 | 22,39 | 5.97 |
JFK
avg_tip | avg_fare | avg_distance | avg_tip_pc | avg_fare_mile |
9.22 | 48,49 | 41.19 | 22,48 | 4.36 |
Umkreisabfragen
Radiusabfragen lassen sich auch ganz einfach in SQL erstellen, wenn Sie sich ein wenig mit Mathematik auskennen. Mit den mathematischen Funktionen von BigQuery Legacy SQL können Sie eine SQL-Abfrage mit der Haversine-Formel erstellen, die eine kreisförmige Fläche oder sphärische Kappe auf der Erdoberfläche annähert.
Hier ist ein Beispiel für eine BigQuery-SQL-Anweisung für eine Kreisabfrage mit dem Mittelpunkt 40.73943, -73.99585
und einem Radius von 0,1 km.
Dabei wird ein konstanter Wert von 111,045 Kilometern verwendet, um die Entfernung zu schätzen, die einem Grad entspricht.
Dieses Beispiel basiert auf einem Beispiel unter http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/:
SELECT pickup_latitude, pickup_longitude,
(111.045 * DEGREES(
ACOS(
COS( RADIANS(40.73943) ) *
COS( RADIANS( pickup_latitude ) ) *
COS(
RADIANS( -73.99585 ) -
RADIANS( pickup_longitude )
) +
SIN( RADIANS(40.73943) ) *
SIN( RADIANS( pickup_latitude ) )
)
)
) AS distance FROM `project.dataset.tableName`
HAVING distance < 0.1
Der SQL-Code für die Haversine-Formel sieht kompliziert aus, aber Sie müssen nur die Koordinaten des Kreismittelpunkts, den Radius sowie die Projekt-, Dataset- und Tabellennamen für BigQuery eingeben.
Hier ist ein Beispiel für eine Abfrage, mit der einige durchschnittliche Fahrtenstatistiken für Abholungen im Umkreis von 100 Metern um das Empire State Building berechnet werden. Kopieren Sie die Abfrage und fügen Sie sie in die BigQuery-Webkonsole ein, um die Ergebnisse zu sehen. Ändern Sie den Breiten- und Längengrad, um ihn mit anderen Gebieten wie dem Standort in der Bronx zu vergleichen.
#standardSQL
CREATE TEMPORARY FUNCTION Degrees(radians FLOAT64) RETURNS FLOAT64 AS
(
(radians*180)/(22/7)
);
CREATE TEMPORARY FUNCTION Radians(degrees FLOAT64) AS (
(degrees*(22/7))/180
);
CREATE TEMPORARY FUNCTION DistanceKm(lat FLOAT64, lon FLOAT64, lat1 FLOAT64, lon1 FLOAT64) AS (
Degrees(
ACOS(
COS( Radians(lat1) ) *
COS( Radians(lat) ) *
COS( Radians(lon1 ) -
Radians( lon ) ) +
SIN( Radians(lat1) ) *
SIN( Radians( lat ) )
)
) * 111.045
);
SELECT
ROUND(AVG(tip_amount),2) as avg_tip,
ROUND(AVG(fare_amount),2) as avg_fare,
ROUND(AVG(trip_distance),2) as avg_distance,
ROUND(AVG(tip_proportion), 2) as avg_tip_pc,
ROUND(AVG(fare_per_mile),2) as avg_fare_mile
FROM
-- EMPIRE STATE BLDG 40.748459, -73.985731
-- BRONX 40.895597, -73.856085
(SELECT pickup_latitude, pickup_longitude, tip_amount, fare_amount, trip_distance, tip_amount/fare_amount*100 as tip_proportion, fare_amount / trip_distance as fare_per_mile, DistanceKm(pickup_latitude, pickup_longitude, 40.748459, -73.985731)
FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2015`
WHERE
DistanceKm(pickup_latitude, pickup_longitude, 40.748459, -73.985731) < 0.1
AND fare_amount > 0 and trip_distance > 0
)
WHERE fare_amount < 100
Die Ergebnisse der Abfrage sind unten aufgeführt. Sie sehen, dass es große Unterschiede beim durchschnittlichen Trinkgeld, beim Fahrpreis, bei der Fahrtstrecke, beim prozentualen Anteil des Trinkgelds am Fahrpreis und beim durchschnittlichen Fahrpreis pro gefahrenem Kilometer gibt.
Empire State Building:
avg_tip | avg_fare | avg_distance | avg_tip_pc | avg_fare_mile |
1.17 | 11.08 | 45.28 | 10.53 | 6.42 |
In Dortmund
avg_tip | avg_fare | avg_distance | avg_tip_pc | avg_fare_mile |
0,52 | 17.63 | 4,75 | 4,74 | 10.9 |
Polygon-Abfragen
SQL unterstützt keine Abfragen mit beliebigen Formen, die keine Rechtecke oder Kreise sind. BigQuery hat keinen nativen Geometriedatentyp oder räumlichen Index. Wenn Sie also Abfragen mit Polygonformen ausführen möchten, benötigen Sie einen anderen Ansatz als bei einfachen SQL-Abfragen. Eine Möglichkeit besteht darin, eine Geometriefunktion in JavaScript zu definieren und sie als benutzerdefinierte Funktion (User-Defined Function, UDF) in BigQuery auszuführen.
Viele Geometrieoperationen können in JavaScript geschrieben werden. Es ist also ganz einfach, eine Operation auszuwählen und für eine BigQuery-Tabelle auszuführen, die Breiten- und Längengradwerte enthält. Sie müssen das benutzerdefinierte Polygon über eine benutzerdefinierte Funktion übergeben und einen Test für jede Zeile durchführen. Es werden nur Zeilen zurückgegeben, in denen sich der Breiten- und Längengrad innerhalb des Polygons befindet. Weitere Informationen zu UDFs in der BigQuery-Referenz
Point-in-Polygon-Algorithmus
Es gibt viele Möglichkeiten, in JavaScript zu berechnen, ob ein Punkt innerhalb eines Polygons liegt. Hier ist ein Port aus C von einer bekannten Implementierung, die einen Raytracing-Algorithmus verwendet, um zu bestimmen, ob sich ein Punkt innerhalb oder außerhalb eines Polygons befindet. Dazu wird gezählt, wie oft eine unendlich lange Linie die Grenze der Form kreuzt. Dafür sind nur wenige Codezeilen erforderlich:
function pointInPoly(nvert, vertx, verty, testx, testy){
var i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
Portierung zu JavaScript
Die JavaScript-Version dieses Algorithmus sieht so aus:
/* This function includes a port of C code to calculate point in polygon
* see http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html for license
*/
function pointInPoly(polygon, point){
// Convert a JSON poly into two arrays and a vertex count.
let vertx = [],
verty = [],
nvert = 0,
testx = point[0],
testy = point[1];
for (let coord of polygon){
vertx[nvert] = coord[0];
verty[nvert] = coord[1];
nvert ++;
}
// The rest of this function is the ported implementation.
for (let i = 0, let j = nvert - 1; i < nvert; j = i++) {
if ( ((verty[i] > testy) != (verty[j] > testy)) &&
(testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
Wenn Sie Standard-SQL in BigQuery verwenden, ist für den UDF-Ansatz nur eine einzige Anweisung erforderlich. Die UDF muss jedoch als temporäre Funktion in der Anweisung definiert werden. Hier ein Beispiel: Fügen Sie die SQL-Anweisung unten in das Fenster „Abfrageeditor“ ein.
CREATE TEMPORARY FUNCTION pointInPolygon(latitude FLOAT64, longitude FLOAT64)
RETURNS BOOL LANGUAGE js AS """
let polygon=[[-73.98925602436066,40.743249676056955],[-73.98836016654968,40.74280666503313],[-73.98915946483612,40.741676770346295],[-73.98967981338501,40.74191656974406]];
let vertx = [],
verty = [],
nvert = 0,
testx = longitude,
testy = latitude,
c = false,
j = nvert - 1;
for (let coord of polygon){
vertx[nvert] = coord[0];
verty[nvert] = coord[1];
nvert ++;
}
// The rest of this function is the ported implementation.
for (let i = 0; i < nvert; j = i++) {
if ( ((verty[i] > testy) != (verty[j] > testy)) &&
(testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]) ) {
c = !c;
}
}
return c;
""";
SELECT pickup_latitude, pickup_longitude, dropoff_latitude, dropoff_longitude, pickup_datetime
FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2016`
WHERE pointInPolygon(pickup_latitude, pickup_longitude) = TRUE
AND (pickup_datetime BETWEEN CAST("2016-01-01 00:00:01" AS DATETIME) AND CAST("2016-02-28 23:59:59" AS DATETIME))
LIMIT 1000
Glückwunsch!
Sie haben jetzt drei Arten von räumlichen Abfragen mit BigQuery ausgeführt. Wie Sie gesehen haben, macht der Standort einen großen Unterschied bei den Ergebnisdaten für die Abfragen für dieses Dataset. Wenn Sie jedoch nicht erraten, wo Sie Ihre Abfragen ausführen müssen, ist es schwierig, räumliche Muster ad hoc nur mit SQL-Abfragen zu erkennen.
Wenn wir die Daten doch nur auf einer Karte visualisieren und untersuchen könnten, indem wir beliebige Interessengebiete definieren! Mit den Google Maps APIs ist das möglich. Zuerst müssen Sie die Maps API aktivieren, eine einfache Webseite auf Ihrem lokalen Computer einrichten und die BigQuery API verwenden, um Abfragen von Ihrer Webseite zu senden.
4. Mit den Google Maps APIs arbeiten
Nachdem Sie einige einfache räumliche Abfragen ausgeführt haben, können Sie die Ausgabe visualisieren, um die Muster zu sehen. Dazu aktivieren Sie die Maps API, erstellen eine Webseite, die Abfragen von einer Karte an BigQuery sendet, und stellen die Ergebnisse dann auf der Karte dar.
Maps JavaScript API aktivieren
Für dieses Codelab müssen Sie die Google Maps JavaScript API der Google Maps Platform in Ihrem Projekt aktivieren. Gehen Sie hierzu wie folgt vor:
- Rufen Sie in der Google Cloud Console den Marketplace auf.
- Suchen Sie im Marketplace nach „Maps JavaScript API“.
- Klicken Sie in den Suchergebnissen auf die Kachel für die Maps JavaScript API.
- Klicken Sie auf die Schaltfläche „Aktivieren“.
API-Schlüssel generieren
Wenn Sie Anfragen an die Google Maps Platform senden möchten, müssen Sie einen API-Schlüssel generieren und mit allen Anfragen senden. So generieren Sie einen API-Schlüssel:
- Klicken Sie in der Google Cloud Console auf das Hamburger-Menü, um die linke Navigationsleiste zu öffnen.
- Wählen Sie „APIs & Dienste“ > „Anmeldedaten“ aus.
- Klicken Sie auf die Schaltfläche „Anmeldedaten erstellen“ und wählen Sie dann „API-Schlüssel“ aus.
- Neuen API-Schlüssel kopieren
Code herunterladen und Webserver einrichten
Klicken Sie auf die folgende Schaltfläche, um den gesamten Code für dieses Codelab herunterzuladen:
Entpacken Sie die heruntergeladene ZIP-Datei. Dadurch wird ein Stammordner (bigquery
) entpackt, der für jeden Schritt dieses Codelabs einen Ordner sowie alle benötigten Ressourcen enthält.
Die stepN
-Ordner enthalten den gewünschten Endstatus jedes Schrittes dieses Codelabs. Sie sind als Referenz verfügbar. Wir werden alle unsere Programmierarbeiten im Verzeichnis work
durchführen.
Lokalen Webserver einrichten
Sie können zwar Ihren eigenen Webserver verwenden, dieses Codelab ist jedoch für die Verwendung mit dem Chrome-Webserver konzipiert. Wenn Sie die App noch nicht installiert haben, können Sie sie im Chrome Web Store installieren.
Öffnen Sie die App nach der Installation. In Chrome geht das so:
- Chrome öffnen
- Geben Sie oben in der Adressleiste „chrome://apps“ ein.
- Drücken Sie die Eingabetaste.
- Klicken Sie im geöffneten Fenster auf das Symbol für den Webserver. Sie können auch mit der rechten Maustaste auf eine App klicken, um sie auf einem normalen oder angepinnten Tab, im Vollbildmodus oder in einem neuen Fenster zu öffnen
. Das folgende Dialogfeld wird angezeigt, in dem Sie Ihren lokalen Webserver konfigurieren können:
- Klicken Sie auf „ORDNER AUSWÄHLEN“ und wählen Sie den Speicherort aus, an den Sie die Codelab-Beispieldateien heruntergeladen haben.
- Klicken Sie im Bereich „Optionen“ das Kästchen neben „index.html automatisch anzeigen“ an:
- Schieben Sie den Schalter mit der Bezeichnung „Webserver: GESTARTET“ nach links und dann wieder nach rechts, um den Webserver zu beenden und neu zu starten.
5. Karte und Zeichenwerkzeuge werden geladen
Einfache Kartenseite erstellen
Beginnen Sie mit einer einfachen HTML-Seite, auf der eine Google-Karte mithilfe der Maps JavaScript API und einigen Zeilen JavaScript geladen wird. Der Code aus dem Beispiel für eine einfache Karte der Google Maps Platform ist ein guter Ausgangspunkt. Sie können ihn hier kopieren und in den Texteditor oder die IDE Ihrer Wahl einfügen. Alternativ können Sie ihn auch öffnen, indem Sie index.html
aus dem heruntergeladenen Repository öffnen.
- Kopieren Sie
index.html
in den Ordnerwork
in Ihrer lokalen Kopie des Repositorys. - Kopieren Sie den Ordner „img/“ in Ihrer lokalen Kopie des Repositorys in den Ordner „work/“.
- Öffnen Sie work/
index.html
in Ihrem Texteditor oder Ihrer IDE. - Ersetzen Sie
YOUR_API_KEY
durch den zuvor erstellten API-Schlüssel.
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
async defer></script>
- Öffnen Sie in Ihrem Browser
localhost:<port>/work
. Dabei istport
die Portnummer, die in der Konfiguration Ihres lokalen Webservers angegeben ist. Der Standardport ist8887
. Ihre erste Karte sollte angezeigt werden.
Wenn Sie eine Fehlermeldung im Browser erhalten, prüfen Sie, ob Ihr API-Schlüssel korrekt ist und Ihr lokaler Webserver aktiv ist.
Standardstandort und ‑zoomstufe ändern
Der Code, mit dem der Standort und der Zoomfaktor festgelegt werden, befindet sich in den Zeilen 27 und 28 von „index.html“. Derzeit ist er auf Sydney, Australien, zentriert:
<script>
let map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
}
</script>
In dieser Anleitung werden BigQuery-Fahrtendaten für New York verwendet. Als Nächstes ändern Sie den Code für die Karteninitialisierung, sodass die Karte auf einen Ort in New York City zentriert wird. Eine Zoomstufe von 13 oder 14 sollte gut funktionieren.
Aktualisieren Sie dazu den Codeblock oben so, dass die Karte auf das Empire State Building zentriert und die Zoomstufe auf 14 festgelegt wird:
<script>
let map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.7484405, lng: -73.9878531},
zoom: 14
});
}
</script>
Aktualisieren Sie dann die Karte in Ihrem Browser, um die Ergebnisse zu sehen.
Zeichnungs- und Visualisierungsbibliotheken laden
Wenn Sie Ihrer Karte Zeichenfunktionen hinzufügen möchten, müssen Sie das Skript zum Laden der Maps JavaScript API ändern. Fügen Sie dazu einen optionalen Parameter hinzu, mit dem Google Maps Platform angewiesen wird, die Drawing Library zu aktivieren.
In diesem Codelab wird auch HeatmapLayer
verwendet. Sie müssen das Skript also aktualisieren, um die Visualisierungsbibliothek anzufordern. Fügen Sie dazu den Parameter libraries
hinzu und geben Sie die Bibliotheken visualization
und drawing
als durch Kommas getrennte Werte an, z. B. libraries=
visualization,drawing
.
Das sollte so aussehen:
<script src='http://maps.googleapis.com/maps/api/js?libraries=visualization,drawing&callback=initMap&key=YOUR_API_KEY' async defer></script>
DrawingManager hinzufügen
Wenn Sie von Nutzern gezeichnete Formen als Eingabe für eine Abfrage verwenden möchten, fügen Sie Ihrer Karte DrawingManager
hinzu und aktivieren Sie die Tools Circle
, Rectangle
und Polygon
.
Es empfiehlt sich, den gesamten Einrichtungscode für DrawingManager
in eine neue Funktion einzufügen. Gehen Sie dazu in Ihrer Kopie von index.html so vor:
- Fügen Sie eine Funktion mit dem Namen
setUpDrawingTools()
mit dem folgenden Code hinzu, umDrawingManager
zu erstellen und die Eigenschaftmap
so festzulegen, dass sie auf das Kartenobjekt auf der Seite verweist.
Mit den an google.maps.drawing.DrawingManager(options)
übergebenen Optionen werden der Standardtyp für das Zeichnen von Formen und die Anzeigeoptionen für gezeichnete Formen festgelegt. Wenn Sie Kartenbereiche für Anfragen auswählen, sollten die Formen eine Deckkraft von null haben. Weitere Informationen zu den verfügbaren Optionen finden Sie unter DrawingManager-Optionen.
function setUpDrawingTools() {
// Initialize drawing manager
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.CIRCLE,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT,
drawingModes: [
google.maps.drawing.OverlayType.CIRCLE,
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.RECTANGLE
]
},
circleOptions: {
fillOpacity: 0
},
polygonOptions: {
fillOpacity: 0
},
rectangleOptions: {
fillOpacity: 0
}
});
drawingManager.setMap(map);
}
- Rufen Sie
setUpDrawingTools()
in IhrerinitMap()
-Funktion auf, nachdem das Kartenobjekt erstellt wurde.
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.744593, lng: -73.990370}, // Manhattan, New York.
zoom: 12
});
setUpDrawingTools();
}
- Laden Sie „index.html“ neu und prüfen Sie, ob die Zeichenwerkzeuge angezeigt werden. Prüfen Sie auch, ob Sie damit Kreise, Rechtecke und Polygone zeichnen können.
Sie können Kreise und Rechtecke durch Klicken und Ziehen zeichnen. Polygone müssen jedoch gezeichnet werden, indem Sie für jeden Scheitelpunkt klicken und dann doppelklicken, um die Form fertigzustellen.
Zeichnungsereignisse verarbeiten
Sie benötigen Code, um die Ereignisse zu verarbeiten, die ausgelöst werden, wenn ein Nutzer eine Form fertig gezeichnet hat. Außerdem benötigen Sie die Koordinaten der gezeichneten Formen, um SQL-Abfragen zu erstellen.
Wir fügen den Code dafür in einem späteren Schritt hinzu. Jetzt erstellen wir erst einmal drei leere Event-Handler für die Ereignisse rectanglecomplete
, circlecomplete
und polygoncomplete
. Die Handler müssen in dieser Phase keinen Code ausführen.
Fügen Sie am Ende der Funktion setUpDrawingTools()
Folgendes hinzu:
drawingManager.addListener('rectanglecomplete', rectangle => {
// We will add code here in a later step.
});
drawingManager.addListener('circlecomplete', circle => {
// We will add code here in a later step.
});
drawingManager.addListener('polygoncomplete', polygon => {
// We will add code here in a later step.
});
Ein funktionierendes Beispiel für diesen Code finden Sie in Ihrer lokalen Kopie des Repositorys im Ordner step2
: step2/map.html.
6. BigQuery Client API verwenden
Mit der Google BigQuery Client API können Sie viel Boilerplate-Code vermeiden, der zum Erstellen der Anfragen, zum Parsen von Antworten und zum Verarbeiten der Authentifizierung erforderlich ist. In diesem Codelab wird die BigQuery API über die Google APIs Client Library for JavaScript verwendet, da wir eine browserbasierte Anwendung entwickeln.
Als Nächstes fügen Sie Code hinzu, um diese API auf einer Webseite zu laden und damit mit BigQuery zu interagieren.
Google Client API für JavaScript hinzufügen
Sie verwenden die Google Client API für Javascript, um Abfragen für BigQuery auszuführen. Laden Sie in Ihrer Kopie von index.html
(in Ihrem Ordner work
) die API mit einem <script>
-Tag wie diesem: Platzieren Sie das Tag direkt unter dem <script>
-Tag, mit dem die Maps API geladen wird:
<script src='https://apis.google.com/js/client.js'></script>
Nachdem Sie die Google Client API geladen haben, autorisieren Sie den Nutzer für den Zugriff auf die Daten in BigQuery. Dazu können Sie OAuth 2.0 verwenden. Zuerst müssen Sie einige Anmeldedaten in Ihrem Google Cloud Console-Projekt einrichten.
OAuth 2.0-Anmeldedaten erstellen
- Wählen Sie in der Google Cloud Console im Navigationsmenü die Option APIs und Dienste > Anmeldedaten aus.
Bevor Sie Ihre Anmeldedaten einrichten können, müssen Sie einige Konfigurationen für den Autorisierungsbildschirm hinzufügen, der einem Endnutzer Ihrer Anwendung angezeigt wird, wenn er Ihre App autorisiert, in seinem Namen auf BigQuery-Daten zuzugreifen.
Klicken Sie dazu auf den Tab OAuth-Zustimmungsbildschirm. 2. Sie müssen die BigQuery API den Bereichen für dieses Token hinzufügen. Klicken Sie im Abschnitt „Bereiche für Google-APIs“ auf die Schaltfläche Bereich hinzufügen. 3. Klicken Sie in der Liste das Kästchen neben dem Eintrag BigQuery API mit dem Bereich ../auth/bigquery
an. 4. Klicken Sie auf Hinzufügen. 5. Geben Sie einen Namen in das Feld „Name der Anwendung“ ein. 6. Klicken Sie auf Speichern, um die Einstellungen zu speichern. 7. Als Nächstes erstellen Sie Ihre OAuth-Client-ID. Klicken Sie dazu auf Anmeldedaten erstellen:
- Klicken Sie im Drop-down-Menü auf OAuth-Client-ID.
- Wählen Sie unter „Anwendungstyp“ die Option Webanwendung aus.
- Geben Sie im Feld „Anwendungsname“ einen Namen für Ihr Projekt ein. Beispiel: „BigQuery und Maps“.
- Geben Sie unter Einschränkungen im Feld „Autorisierte JavaScript-Quellen“ die URL von „localhost“ ein, einschließlich der Portnummern. Beispiel:
http://localhost:8887
- Klicken Sie auf Erstellen.
In einem Pop-up-Fenster werden die Client-ID und der Clientschlüssel angezeigt. Sie benötigen die Client-ID, um die Authentifizierung für BigQuery durchzuführen. Kopieren Sie ihn und fügen Sie ihn in work/index.html
als neue globale JavaScript-Variable mit dem Namen clientId
ein.
let clientId = 'YOUR_CLIENT_ID';
7. Autorisierung und Initialisierung
Auf Ihrer Webseite muss der Nutzer autorisiert werden, auf BigQuery zuzugreifen, bevor die Karte initialisiert wird. In diesem Beispiel verwenden wir OAuth 2.0, wie im Autorisierungsabschnitt der JavaScript Client API-Dokumentation beschrieben. Sie benötigen die OAuth-Client-ID und Ihre Projekt-ID, um Anfragen zu senden.
Wenn die Google Client API auf der Webseite geladen wird, müssen Sie die folgenden Schritte ausführen:
- Autorisieren Sie den Nutzer.
- Wenn die Autorisierung erfolgt ist, laden Sie die BigQuery API.
- Laden und initialisieren Sie die Karte.
Ein Beispiel für die fertige HTML-Seite finden Sie unter step3/map.html.
Nutzer autorisieren
Der Endnutzer der Anwendung muss die Anwendung autorisieren, in seinem Namen auf Daten in BigQuery zuzugreifen. Die Google Client API für JavaScript übernimmt die OAuth-Logik dafür.
In einer realen Anwendung haben Sie viele Möglichkeiten, den Autorisierungsschritt zu integrieren.
Sie können authorize()
beispielsweise über ein UI-Element wie eine Schaltfläche aufrufen oder wenn die Seite geladen wurde. Hier haben wir uns dafür entschieden, den Nutzer zu autorisieren, nachdem die Google Client API für JavaScript geladen wurde. Dazu verwenden wir eine Callback-Funktion in der gapi.load()
-Methode.
Schreiben Sie direkt nach dem <script>
-Tag Code, der die Google Client API für Javascript lädt, um sowohl die Clientbibliothek als auch das Authentifizierungsmodul zu laden, damit wir den Nutzer sofort authentifizieren können.
<script src='https://apis.google.com/js/client.js'></script>
<script type='text/javascript'>
gapi.load('client:auth', authorize);
</script>
BigQuery API nach der Autorisierung laden
Nachdem der Nutzer autorisiert wurde, laden Sie die BigQuery API.
Rufen Sie zuerst gapi.auth.authorize()
mit der Variablen clientId
auf, die Sie im vorherigen Schritt hinzugefügt haben. Verarbeiten Sie die Antwort in einer Callback-Funktion namens handleAuthResult
.
Mit dem Parameter immediate
wird gesteuert, ob dem Nutzer ein Pop-up angezeigt wird. Legen Sie den Wert auf true
fest, um das Autorisierungs-Pop-up zu unterdrücken, wenn der Nutzer bereits autorisiert ist.
Fügen Sie Ihrer Seite eine Funktion namens handleAuthResult()
hinzu. Die Funktion muss einen authresult
-Parameter enthalten, mit dem Sie den Ablauf der Logik steuern können, je nachdem, ob der Nutzer erfolgreich autorisiert wurde oder nicht.
Fügen Sie außerdem eine Funktion namens loadApi
hinzu, um die BigQuery API zu laden, wenn der Nutzer erfolgreich autorisiert wurde.
Fügen Sie der Funktion handleAuthResult()
Logik hinzu, um loadApi()
aufzurufen, wenn ein authResult
-Objekt an die Funktion übergeben wird und die error
-Eigenschaft des Objekts den Wert false
hat.
Fügen Sie der Funktion loadApi()
Code hinzu, um die BigQuery API mit der Methode gapi.client.load()
zu laden.
let clientId = 'your-client-id-here';
let scopes = 'https://www.googleapis.com/auth/bigquery';
// Check if the user is authorized.
function authorize(event) {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
return false;
}
// If authorized, load BigQuery API
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
loadApi();
return;
}
console.error('Not authorized.')
}
// Load BigQuery client API
function loadApi(){
gapi.client.load('bigquery', 'v2');
}
Karte laden
Im letzten Schritt wird die Karte initialisiert. Dazu müssen Sie die Reihenfolge der Logik leicht ändern. Derzeit wird sie initialisiert, wenn das Maps API-JavaScript geladen wurde.
Rufen Sie dazu die Funktion initMap()
über die Methode then()
nach der Methode load()
für das gapi.client
-Objekt auf.
// Load BigQuery client API
function loadApi(){
gapi.client.load('bigquery', 'v2').then(
() => initMap()
);
}
8. BigQuery API-Konzepte
BigQuery API-Aufrufe werden in der Regel innerhalb von Sekunden ausgeführt, geben aber möglicherweise nicht sofort eine Antwort zurück. Sie benötigen eine Logik, um BigQuery abzufragen, um den Status von Jobs mit langer Ausführungszeit zu ermitteln und die Ergebnisse erst abzurufen, wenn der Job abgeschlossen ist.
Der vollständige Code für diesen Schritt befindet sich in step4/map.html.
Anfrage senden
Fügen Sie work/index.html
eine JavaScript-Funktion hinzu, um eine Abfrage über die API zu senden, sowie einige Variablen, um die Werte des BigQuery-Datasets und des Projekts mit der abzufragenden Tabelle sowie die Projekt-ID zu speichern, die für alle Gebühren in Rechnung gestellt wird.
let datasetId = 'your_dataset_id';
let billingProjectId = 'your_project_id';
let publicProjectId = 'bigquery-public-data';
function sendQuery(queryString){
let request = gapi.client.bigquery.jobs.query({
'query': queryString,
'timeoutMs': 30000,
'datasetId': datasetId,
'projectId': billingProjectId,
'useLegacySql':false
});
request.execute(response => {
//code to handle the query response goes here.
});
}
Status eines Jobs prüfen
Die Funktion checkJobStatus
unten zeigt, wie der Status eines Jobs regelmäßig geprüft wird. Dies erfolgt durch Aufruf der API-Methode get
mit der jobId
, die von der ursprünglichen Anfrage zurückgegeben wurde. Hier ist ein Beispiel, das alle 500 Millisekunden ausgeführt wird, bis der Job abgeschlossen ist.
let jobCheckTimer;
function checkJobStatus(jobId){
let request = gapi.client.bigquery.jobs.get({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response =>{
if (response.status.errorResult){
// Handle any errors.
console.log(response.status.error);
return;
}
if (response.status.state == 'DONE'){
// Get the results.
clearTimeout(jobCheckTimer);
getQueryResults(jobId);
return;
}
// Not finished, check again in a moment.
jobCheckTimer = setTimeout(checkJobStatus, 500, [jobId]);
});
}
Ändern Sie die sendQuery
-Methode so, dass die checkJobStatus()
-Methode als Callback im request.execute()
-Aufruf aufgerufen wird. Übergeben Sie die Job-ID an checkJobStatus
. Dies wird vom Antwortobjekt als jobReference.jobId
bereitgestellt.
function sendQuery(queryString){
let request = gapi.client.bigquery.jobs.query({
'query': queryString,
'timeoutMs': 30000,
'datasetId': datasetId,
'projectId': billingProjectId,
'useLegacySql':false
});
request.execute(response => checkJobStatus(response.jobReference.jobId));
}
Abfrageergebnisse abrufen
Verwenden Sie den API-Aufruf jobs.getQueryResults
, um die Ergebnisse einer Abfrage abzurufen, wenn sie abgeschlossen ist. Fügen Sie Ihrer Seite eine Funktion mit dem Namen getQueryResults()
hinzu, die den Parameter jobId
akzeptiert:
function getQueryResults(jobId){
let request = gapi.client.bigquery.jobs.getQueryResults({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response => {
// Do something with the results.
})
}
9. Standortdaten mit der BigQuery API abfragen
Es gibt drei Möglichkeiten, SQL für räumliche Abfragen von Daten in BigQuery zu nutzen:
- mit einem Rechteck (auch als Begrenzungsrahmen bezeichnet)
- nach Radius auswählen und
- die leistungsstarke Funktion Benutzerdefinierte Funktionen.
Beispiele für Begrenzungsrahmen- und Radiusabfragen finden Sie in der BigQuery Legacy-SQL-Referenz im Abschnitt „Mathematische Funktionen“ unter „Erweiterte Beispiele“.
Für Anfragen zu Begrenzungsrahmen und Radius können Sie die BigQuery API-Methode query
aufrufen. Erstellen Sie den SQL-Code für jede Abfrage und übergeben Sie ihn an die Funktion sendQuery
, die Sie im vorherigen Schritt erstellt haben.
Ein funktionierendes Beispiel für den Code für diesen Schritt finden Sie unter step4/map.html.
Rechteckabfragen
Die einfachste Methode zum Anzeigen von BigQuery-Daten auf einer Karte besteht darin, alle Zeilen abzurufen, in denen sich der Breiten- und Längengrad innerhalb eines Rechtecks befindet. Dazu verwenden Sie einen Vergleich mit „kleiner als“ und „größer als“. Das kann die aktuelle Kartenansicht oder eine auf der Karte gezeichnete Form sein.
Wenn Sie eine vom Nutzer gezeichnete Form verwenden möchten, ändern Sie den Code in index.html
, um das Zeichenereignis zu verarbeiten, das ausgelöst wird, wenn ein Rechteck fertig gezeichnet ist. In diesem Beispiel wird mit dem Code getBounds()
für das Rechteckobjekt verwendet, um ein Objekt abzurufen, das die Ausdehnung des Rechtecks in Kartenkoordinaten darstellt. Dieses Objekt wird an eine Funktion namens rectangleQuery
übergeben:
drawingManager.addListener('rectanglecomplete', rectangle => rectangleQuery(rectangle.getBounds()));
Für die rectangleQuery
-Funktion müssen nur die Koordinaten oben rechts (Nordosten) und unten links (Südwesten) verwendet werden, um einen Vergleich vom Typ „Kleiner als“ / „Größer als“ für jede Zeile in Ihrer BigQuery-Tabelle zu erstellen. Hier ist ein Beispiel für eine Abfrage einer Tabelle mit Spalten namens 'pickup_latitude'
und 'pickup_longitude'
, in denen die Standortwerte gespeichert sind.
BigQuery-Tabelle angeben
Wenn Sie eine Tabelle mit der BigQuery API abfragen möchten, müssen Sie den Namen der Tabelle in Ihrer SQL-Abfrage in vollständig qualifizierter Form angeben. Das Format in Standard-SQL ist project.dataset.tablename
. In Legacy-SQL ist es project.dataset.tablename
.
Es gibt viele Tabellen mit NYC Taxi-Fahrten. Rufen Sie die BigQuery-Webkonsole auf und maximieren Sie den Menüpunkt „Öffentliche Datasets“, um sie zu sehen. Suchen Sie nach dem Dataset mit dem Namen new_york
und maximieren Sie es, um die Tabellen aufzurufen. Wählen Sie die Tabelle „Yellow Taxi trips“ (bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2016
) aus.
Projekt-ID angeben
Im API-Aufruf müssen Sie den Namen Ihres Google Cloud-Projekts für Abrechnungszwecke angeben. In diesem Codelab ist das nicht dasselbe Projekt wie das, das die Tabelle enthält. Wenn Sie mit einer Tabelle arbeiten, die Sie in Ihrem eigenen Projekt durch Hochladen von Daten erstellt haben, entspricht diese Projekt-ID der in Ihrer SQL-Anweisung.
Fügen Sie Ihrem Code JavaScript-Variablen hinzu, um Verweise auf das Projekt „Public Datasets“ mit der Tabelle, die Sie abfragen, sowie den Tabellen- und Dataset-Namen zu speichern. Außerdem benötigen Sie eine separate Variable, um auf Ihre eigene Abrechnungsprojekt-ID zu verweisen.
Fügen Sie Ihrer Kopie von index.html globale JavaScript-Variablen mit den Namen billingProjectId, publicProjectId, datasetId
und tableName
hinzu.
Initialisieren Sie die Variablen 'publicProjectId'
, 'datasetId'
und 'tableName'
mit den Details aus dem Projekt „BigQuery Public Datasets“. Initialisieren Sie billingProjectId
mit Ihrer eigenen Projekt-ID (der, die Sie zuvor in diesem Codelab unter „Einrichtung“ erstellt haben).
let billingProjectId = 'YOUR_PROJECT_ID';
let publicProjectId = 'bigquery-public-data';
let datasetId = 'new_york_taxi_trips';
let tableName = 'tlc_yellow_trips_2016';
Fügen Sie Ihrem Code nun zwei Funktionen hinzu, um den SQL-Code zu generieren und die Abfrage mit der sendQuery
-Funktion, die Sie im vorherigen Schritt erstellt haben, an BigQuery zu senden.
Die erste Funktion sollte rectangleSQL()
heißen und zwei Argumente akzeptieren: ein Paar von google.Maps.LatLng
-Objekten, die die Ecken des Rechtecks in Kartenkoordinaten darstellen.
Die zweite Funktion sollte rectangleQuery()
heißen. Dadurch wird der Abfragetext an die Funktion sendQuery
übergeben.
let billingProjectId = 'YOUR_PROJECT_ID';
let publicProjectId = 'bigquery-public-data';
let datasetId = 'new_york';
let tableName = 'tlc_yellow_trips_2016';
function rectangleQuery(latLngBounds){
let queryString = rectangleSQL(latLngBounds.getNorthEast(), latLngBounds.getSouthWest());
sendQuery(queryString);
}
function rectangleSQL(ne, sw){
let queryString = 'SELECT pickup_latitude, pickup_longitude '
queryString += 'FROM `' + publicProjectId +'.' + datasetId + '.' + tableName + '`'
queryString += ' WHERE pickup_latitude > ' + sw.lat();
queryString += ' AND pickup_latitude < ' + ne.lat();
queryString += ' AND pickup_longitude > ' + sw.lng();
queryString += ' AND pickup_longitude < ' + ne.lng();
return queryString;
}
An diesem Punkt haben Sie genügend Code, um eine Abfrage für alle Zeilen, die in einem vom Nutzer gezeichneten Rechteck enthalten sind, an BigQuery zu senden. Bevor wir weitere Abfragemethoden für Kreise und Freihandformen hinzufügen, sehen wir uns an, wie die Daten verarbeitet werden, die von einer Abfrage zurückgegeben werden.
10. Antwort visualisieren
BigQuery-Tabellen können sehr groß sein (Petabyte an Daten) und um Hunderttausende von Zeilen pro Sekunde wachsen. Daher ist es wichtig, die zurückgegebenen Daten so weit wie möglich zu begrenzen, damit sie auf der Karte dargestellt werden können. Wenn Sie den Standort jeder Zeile in einem sehr großen Ergebnis-Set (Zehntausende von Zeilen oder mehr) darstellen, ist die Karte nicht mehr lesbar. Es gibt viele Möglichkeiten, die Standorte sowohl in der SQL-Abfrage als auch auf der Karte zu aggregieren. Außerdem können Sie die Ergebnisse einer Abfrage einschränken.
Der vollständige Code für diesen Schritt ist in step5/map.html verfügbar.
Damit die Menge der auf Ihre Webseite übertragenen Daten für dieses Codelab nicht zu groß wird, ändern Sie die Funktion rectangleSQL()
so, dass die Antwort auf 10.000 Zeilen begrenzt wird. Im folgenden Beispiel wird dies in einer globalen Variablen namens recordLimit
angegeben, damit alle Abfragefunktionen denselben Wert verwenden können.
let recordLimit = 10000;
function rectangleSQL(ne, sw){
var queryString = 'SELECT pickup_latitude, pickup_longitude '
queryString += 'FROM `' + publicProjectId +'.' + datasetId + '.' + tableName + '`'
queryString += ' WHERE pickup_latitude > ' + sw.lat();
queryString += ' AND pickup_latitude < ' + ne.lat();
queryString += ' AND pickup_longitude > ' + sw.lng();
queryString += ' AND pickup_longitude < ' + ne.lng();
queryString += ' LIMIT ' + recordLimit;
return queryString;
}
Mit einer Heatmap lässt sich die Dichte von Standorten visualisieren. Die Maps JavaScript API bietet dafür die Klasse HeatmapLayer. Die HeatmapLayer akzeptiert ein Array von Breiten- und Längengradkoordinaten. Daher ist es ganz einfach, die von der Abfrage zurückgegebenen Zeilen in eine Heatmap umzuwandeln.
Übergeben Sie in der Funktion getQueryResults
das Array response.result.rows
an eine neue JavaScript-Funktion namens doHeatMap()
, die eine Heatmap erstellt.
Jede Zeile hat ein Attribut namens f
, das ein Array von Spalten ist. Jede Spalte hat ein v
-Attribut mit dem Wert.
Ihr Code muss die Spalten in jeder Zeile durchlaufen und die Werte extrahieren.
In der SQL-Abfrage haben Sie nur nach den Breiten- und Längengradwerten der Taxiabholungen gefragt. Die Antwort enthält daher nur zwei Spalten.
Vergessen Sie nicht, setMap()
für die Heatmap-Ebene aufzurufen, nachdem Sie ihr das Array mit Positionen zugewiesen haben. Dadurch wird es auf der Karte sichtbar.
Beispiel:
function getQueryResults(jobId){
let request = gapi.client.bigquery.jobs.getQueryResults({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response => doHeatMap(response.result.rows))
}
let heatmap;
function doHeatMap(rows){
let heatmapData = [];
if (heatmap != null){
heatmap.setMap(null);
}
for (let i = 0; i < rows.length; i++) {
let f = rows[i].f;
let coords = { lat: parseFloat(f[0].v), lng: parseFloat(f[1].v) };
let latLng = new google.maps.LatLng(coords);
heatmapData.push(latLng);
}
heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData
});
heatmap.setMap(map);
}
An diesem Punkt sollten Sie Folgendes können:
- Seite öffnen und für BigQuery autorisieren
- Zeichnen Sie ein Rechteck an einer beliebigen Stelle in New York City.
- Die Abfrageergebnisse werden als Heatmap visualisiert.
Hier sehen Sie ein Beispiel für das Ergebnis einer Rechteckabfrage für die Daten der New Yorker Yellow Taxis von 2016, dargestellt als Heatmap. Hier sehen Sie die Verteilung der Abholungen rund um das Empire State Building an einem Samstag im Juli:
11. Abfrage nach Umkreis um einen Punkt
Radiusabfragen sind sehr ähnlich. Mit den mathematischen Funktionen von BigQuery Legacy SQL können Sie eine SQL-Abfrage mit der Haversine-Formel erstellen, die eine kreisförmige Fläche auf der Erdoberfläche annähert.
Mit derselben Technik für Rechtecke können Sie ein OverlayComplete
-Ereignis verarbeiten, um den Mittelpunkt und den Radius eines vom Nutzer gezeichneten Kreises zu ermitteln, und die SQL-Abfrage auf dieselbe Weise erstellen.
Ein funktionierendes Beispiel für den Code für diesen Schritt ist im Code-Repository als step6/map.html enthalten.
drawingManager.addListener('circlecomplete', circle => circleQuery(circle));
Fügen Sie in Ihre Kopie von „index.html“ zwei neue leere Funktionen ein: circleQuery()
und haversineSQL()
.
Fügen Sie dann einen circlecomplete
-Ereignishandler hinzu, der den Mittelpunkt und den Radius an eine neue Funktion namens circleQuery().
übergibt.
Die Funktion circleQuery()
ruft haversineSQL()
auf, um den SQL-Code für die Abfrage zu erstellen, und sendet die Abfrage dann durch Aufrufen der Funktion sendQuery()
, wie im folgenden Beispielcode gezeigt.
function circleQuery(circle){
let queryString = haversineSQL(circle.getCenter(), circle.radius);
sendQuery(queryString);
}
// Calculate a circular area on the surface of a sphere based on a center and radius.
function haversineSQL(center, radius){
let queryString;
let centerLat = center.lat();
let centerLng = center.lng();
let kmPerDegree = 111.045;
queryString = 'CREATE TEMPORARY FUNCTION Degrees(radians FLOAT64) RETURNS FLOAT64 LANGUAGE js AS ';
queryString += '""" ';
queryString += 'return (radians*180)/(22/7);';
queryString += '"""; ';
queryString += 'CREATE TEMPORARY FUNCTION Radians(degrees FLOAT64) RETURNS FLOAT64 LANGUAGE js AS';
queryString += '""" ';
queryString += 'return (degrees*(22/7))/180;';
queryString += '"""; ';
queryString += 'SELECT pickup_latitude, pickup_longitude '
queryString += 'FROM `' + publicProjectId +'.' + datasetId + '.' + tableName + '` ';
queryString += 'WHERE '
queryString += '(' + kmPerDegree + ' * DEGREES( ACOS( COS( RADIANS('
queryString += centerLat;
queryString += ') ) * COS( RADIANS( pickup_latitude ) ) * COS( RADIANS( ' + centerLng + ' ) - RADIANS('
queryString += ' pickup_longitude ';
queryString += ') ) + SIN( RADIANS('
queryString += centerLat;
queryString += ') ) * SIN( RADIANS( pickup_latitude ) ) ) ) ) ';
queryString += ' < ' + radius/1000;
queryString += ' LIMIT ' + recordLimit;
return queryString;
}
Testen!
Fügen Sie den oben stehenden Code hinzu und versuchen Sie, mit dem Tool „Kreis“ einen Kartenbereich auszuwählen. Das Ergebnis sollte in etwa so aussehen:
12. Beliebige Formen abfragen
Zusammenfassung: In SQL können nur rechteckige und kreisförmige Formen abgefragt werden. BigQuery hat keinen nativen Geometriedatentyp. Wenn Sie also Abfragen mit Polygonformen ausführen möchten, benötigen Sie einen anderen Ansatz als einfache SQL-Abfragen.
Eine sehr leistungsstarke BigQuery-Funktion, die dafür verwendet werden kann, sind benutzerdefinierte Funktionen (User-Defined Functions, UDFs). Mit UDFs wird JavaScript-Code in einer SQL-Abfrage ausgeführt.
Der funktionierende Code für diesen Schritt befindet sich in step7/map.html.
UDFs in der BigQuery API
Der BigQuery API-Ansatz für UDFs unterscheidet sich geringfügig von der Webkonsole: Sie müssen jobs.insert method
aufrufen.
Für Standard-SQL-Abfragen über die API ist nur eine einzige SQL-Anweisung erforderlich, um eine benutzerdefinierte Funktion zu verwenden. Der Wert von useLegacySql
muss auf false
festgelegt werden. Das folgende JavaScript-Beispiel zeigt eine Funktion, die ein Anfrageobjekt erstellt und sendet, um einen neuen Job einzufügen. In diesem Fall handelt es sich um eine Abfrage mit einer benutzerdefinierten Funktion.
Ein funktionierendes Beispiel für diesen Ansatz finden Sie unter step7/map.html.
function polygonQuery(polygon) {
let request = gapi.client.bigquery.jobs.insert({
'projectId' : billingProjectId,
'resource' : {
'configuration':
{
'query':
{
'query': polygonSql(polygon),
'useLegacySql': false
}
}
}
});
request.execute(response => checkJobStatus(response.jobReference.jobId));
}
Die SQL-Abfrage wird so erstellt:
function polygonSql(poly){
let queryString = 'CREATE TEMPORARY FUNCTION pointInPolygon(latitude FLOAT64, longitude FLOAT64) ';
queryString += 'RETURNS BOOL LANGUAGE js AS """ ';
queryString += 'var polygon=' + JSON.stringify(poly) + ';';
queryString += 'var vertx = [];';
queryString += 'var verty = [];';
queryString += 'var nvert = 0;';
queryString += 'var testx = longitude;';
queryString += 'var testy = latitude;';
queryString += 'for(coord in polygon){';
queryString += ' vertx[nvert] = polygon[coord][0];';
queryString += ' verty[nvert] = polygon[coord][1];';
queryString += ' nvert ++;';
queryString += '}';
queryString += 'var i, j, c = 0;';
queryString += 'for (i = 0, j = nvert-1; i < nvert; j = i++) {';
queryString += ' if ( ((verty[i]>testy) != (verty[j]>testy)) &&(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ){';
queryString += ' c = !c;';
queryString += ' }';
queryString += '}';
queryString += 'return c;';
queryString += '"""; ';
queryString += 'SELECT pickup_latitude, pickup_longitude, dropoff_latitude, dropoff_longitude, pickup_datetime ';
queryString += 'FROM `' + publicProjectId + '.' + datasetId + '.' + tableName + '` ';
queryString += 'WHERE pointInPolygon(pickup_latitude, pickup_longitude) = TRUE ';
queryString += 'LIMIT ' + recordLimit;
return queryString;
}
Hier sind zwei Dinge zu beachten. Zuerst wird mit dem Code die CREATE TEMPORARY FUNCTION
-Anweisung erstellt, die den JavaScript-Code kapselt, um zu ermitteln, ob sich ein bestimmter Punkt innerhalb eines Polygons befindet. Die Polygonkoordinaten werden mit dem Methodenaufruf JSON.stringify(poly)
eingefügt, um ein JavaScript-Array von x,y-Koordinatenpaaren in einen String zu konvertieren. Das Polygonobjekt wird als Argument an die Funktion übergeben, die den SQL-Code erstellt.
Zweitens wird mit dem Code die SQL-Hauptanweisung SELECT
erstellt. Die UDF wird in diesem Beispiel im Ausdruck WHERE
aufgerufen.
In die Maps API einbinden
Damit wir das mit der Maps API-Zeichenbibliothek verwenden können, müssen wir das vom Nutzer gezeichnete Polygon speichern und an den UDF-Teil der SQL-Abfrage übergeben.
Zuerst müssen wir das Zeichenereignis polygoncomplete
verarbeiten, um die Koordinaten der Form als Array von Längen- und Breitengradpaaren abzurufen:
drawingManager.addListener('polygoncomplete', polygon => {
let path = polygon.getPaths().getAt(0);
let queryPolygon = path.map(element => {
return [element.lng(), element.lat()];
});
polygonQuery(queryPolygon);
});
Die Funktion polygonQuery
kann dann die UDF-JavaScript-Funktionen als String sowie die SQL-Anweisung erstellen, mit der die UDF-Funktion aufgerufen wird.
Ein funktionierendes Beispiel finden Sie unter step7/map.html.
Beispielausgabe
Hier sehen Sie ein Beispiel für das Ergebnis einer Abfrage von Abholorten aus den NYC TLC Yellow Taxi-Daten von 2016 in BigQuery mit einem Freihandpolygon. Die ausgewählten Daten werden als Heatmap dargestellt.
13. Weitere Informationen
Hier sind einige Vorschläge, wie Sie dieses Codelab erweitern können, um andere Aspekte der Daten zu untersuchen. Ein funktionierendes Beispiel für diese Ideen finden Sie im Code-Repository unter step8/map.html.
Rückgänge zuordnen
Bisher haben wir nur Abholorte kartiert. Wenn Sie die Spalten dropoff_latitude
und dropoff_longitude
anfordern und den Heatmap-Code so ändern, dass diese Spalten dargestellt werden, können Sie die Ziele von Taxifahrten sehen, die an einem bestimmten Ort begonnen haben.
Sehen wir uns zum Beispiel an, wo Taxis Personen absetzen, wenn sie in der Nähe des Empire State Building abgeholt werden.
Ändern Sie den Code für die SQL-Anweisung in polygonSql()
, um diese Spalten zusätzlich zum Abholort anzufordern.
function polygonSql(poly){
let queryString = 'CREATE TEMPORARY FUNCTION pointInPolygon(latitude FLOAT64, longitude FLOAT64) ';
queryString += 'RETURNS BOOL LANGUAGE js AS """ ';
queryString += 'var polygon=' + JSON.stringify(poly) + ';';
queryString += 'var vertx = [];';
queryString += 'var verty = [];';
queryString += 'var nvert = 0;';
queryString += 'var testx = longitude;';
queryString += 'var testy = latitude;';
queryString += 'for(coord in polygon){';
queryString += ' vertx[nvert] = polygon[coord][0];';
queryString += ' verty[nvert] = polygon[coord][1];';
queryString += ' nvert ++;';
queryString += '}';
queryString += 'var i, j, c = 0;';
queryString += 'for (i = 0, j = nvert-1; i < nvert; j = i++) {';
queryString += ' if ( ((verty[i]>testy) != (verty[j]>testy)) &&(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ){';
queryString += ' c = !c;';
queryString += ' }';
queryString += '}';
queryString += 'return c;';
queryString += '"""; ';
queryString += 'SELECT pickup_latitude, pickup_longitude, dropoff_latitude, dropoff_longitude, pickup_datetime ';
queryString += 'FROM `' + publicProjectId + '.' + datasetId + '.' + tableName + '` ';
queryString += 'WHERE pointInPolygon(pickup_latitude, pickup_longitude) = TRUE ';
queryString += 'LIMIT ' + recordLimit;
return queryString;
}
Die doHeatMap
-Funktion kann dann stattdessen die Drop-off-Werte verwenden. Das Ergebnisobjekt hat ein Schema, das untersucht werden kann, um die Position dieser Spalten im Array zu ermitteln. In diesem Fall wären sie an den Indexpositionen 2 und 3. Diese Indexe können aus einer Variablen gelesen werden, um den Code übersichtlicher zu gestalten. Hinweis: Die maxIntensity
der Heatmap ist so eingestellt, dass maximal 20 Abbrüche pro Pixel angezeigt werden.
Fügen Sie einige Variablen hinzu, damit Sie ändern können, welche Spalten für die Heatmap-Daten verwendet werden.
// Show query results as a Heatmap.
function doHeatMap(rows){
let latCol = 2;
let lngCol = 3;
let heatmapData = [];
if (heatmap!=null){
heatmap.setMap(null);
}
for (let i = 0; i < rows.length; i++) {
let f = rows[i].f;
let coords = { lat: parseFloat(f[latCol].v), lng: parseFloat(f[lngCol].v) };
let latLng = new google.maps.LatLng(coords);
heatmapData.push(latLng);
}
heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
maxIntensity: 20
});
heatmap.setMap(map);
}
Hier sehen Sie eine Heatmap mit der Verteilung der Abholorte in unmittelbarer Nähe des Empire State Building im Jahr 2016. Sie sehen große Konzentrationen (die roten Punkte) von Zielen in Midtown, insbesondere rund um den Times Square, sowie entlang der 5th Avenue zwischen der 23rd Street und der 14th Street. Andere Orte mit hoher Dichte, die auf dieser Zoomstufe nicht angezeigt werden, sind die Flughäfen La Guardia und JFK, das World Trade Center und der Battery Park.
Basiskarte gestalten
Wenn Sie eine Google-Karte mit der Maps JavaScript API erstellen, können Sie den Kartenstil mit einem JSON-Objekt festlegen. Bei Datenvisualisierungen kann es sinnvoll sein, die Farben auf der Karte zu dämpfen. Mit dem Google Maps API Styling Wizard unter mapstyle.withgoogle.com können Sie Kartenstile erstellen und ausprobieren.
Sie können einen Kartenstil festlegen, wenn Sie ein Kartenobjekt initialisieren, oder zu einem beliebigen späteren Zeitpunkt. So fügen Sie einen benutzerdefinierten Stil in der Funktion initMap()
hinzu:
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.744593, lng: -73.990370}, // Manhattan, New York.
zoom: 12,
styles: [
{
"elementType": "geometry",
"stylers": [
{
"color": "#f5f5f5"
}
]
},
{
"elementType": "labels.icon",
"stylers": [
{
"visibility": "on"
}
]
},
{
"featureType": "water",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
}
]
});
setUpDrawingTools();
}
Das folgende Beispiel zeigt eine Graustufenkarte mit POI-Labels.
[
{
"elementType": "geometry",
"stylers": [
{
"color": "#f5f5f5"
}
]
},
{
"elementType": "labels.icon",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#f5f5f5"
}
]
},
{
"featureType": "administrative.land_parcel",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#bdbdbd"
}
]
},
{
"featureType": "poi",
"elementType": "geometry",
"stylers": [
{
"color": "#eeeeee"
}
]
},
{
"featureType": "poi",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "poi.park",
"elementType": "geometry",
"stylers": [
{
"color": "#e5e5e5"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
},
{
"featureType": "road",
"elementType": "geometry",
"stylers": [
{
"color": "#ffffff"
}
]
},
{
"featureType": "road.arterial",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
{
"color": "#dadada"
}
]
},
{
"featureType": "road.highway",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "road.local",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
},
{
"featureType": "transit.line",
"elementType": "geometry",
"stylers": [
{
"color": "#e5e5e5"
}
]
},
{
"featureType": "transit.station",
"elementType": "geometry",
"stylers": [
{
"color": "#eeeeee"
}
]
},
{
"featureType": "water",
"elementType": "geometry",
"stylers": [
{
"color": "#c9c9c9"
}
]
},
{
"featureType": "water",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
}
]
Nutzerfeedback geben
Auch wenn BigQuery in der Regel innerhalb von Sekunden eine Antwort liefert, ist es manchmal sinnvoll, dem Nutzer zu zeigen, dass etwas passiert, während die Abfrage ausgeführt wird.
Fügen Sie Ihrer Webseite eine Benutzeroberfläche hinzu, auf der die Antwort der checkJobStatus()
-Funktion angezeigt wird, sowie eine animierte Grafik, die angibt, dass die Anfrage läuft.
Sie können unter anderem die Abfragedauer, die zurückgegebene Datenmenge und die verarbeitete Datenmenge anzeigen lassen.
Fügen Sie nach dem <div>
-Tag der Karte etwas HTML-Code ein, um ein Feld auf der Seite zu erstellen, in dem die Anzahl der von einer Abfrage zurückgegebenen Zeilen, die Ausführungszeit der Abfrage und die verarbeitete Datenmenge angezeigt werden.
<div id="menu">
<div id="stats">
<h3>Statistics:</h3>
<table>
<tr>
<td>Total Locations:</td><td id="rowCount"> - </td>
</tr>
<tr>
<td>Query Execution:</td><td id="duration"> - </td>
</tr>
<tr>
<td>Data Processed:</td><td id="bytes"> - </td>
</tr>
</table>
</div>
</div>
Darstellung und Position dieses Bereichs werden über CSS gesteuert. Fügen Sie CSS hinzu, um das Feld oben links auf der Seite unter den Schaltflächen für den Kartentyp und der Zeichen-Symbolleiste zu positionieren, wie im Snippet unten.
#menu {
position: absolute;
background: rgba(255, 255, 255, 0.8);
z-index: 1000;
top: 50px;
left: 10px;
padding: 15px;
}
#menu h1 {
margin: 0 0 10px 0;
font-size: 1.75em;
}
#menu div {
margin: 5px 0px;
}
Die animierte Grafik kann der Seite hinzugefügt, aber bis zum Bedarf ausgeblendet werden. Mit JavaScript- und CSS-Code kann sie dann angezeigt werden, wenn ein BigQuery-Job ausgeführt wird.
Fügen Sie HTML-Code hinzu, um eine animierte Grafik anzuzeigen. Im Ordner img
im Code-Repository befindet sich eine Bilddatei mit dem Namen loader.gif
.
<img id="spinner" src="img/loader.gif">
Fügen Sie etwas CSS hinzu, um das Bild zu positionieren und es standardmäßig auszublenden, bis es benötigt wird.
#spinner {
position: absolute;
top: 50%;
left: 50%;
margin-left: -32px;
margin-top: -32px;
opacity: 0;
z-index: -1000;
}
Fügen Sie zum Schluss etwas JavaScript hinzu, um das Statusfeld zu aktualisieren und die Grafik ein- oder auszublenden, wenn eine Abfrage ausgeführt wird. Mit dem response
-Objekt können Sie den Bereich je nach verfügbaren Informationen aktualisieren.
Wenn Sie einen aktuellen Job prüfen, können Sie die Property response.statistics
verwenden. Nach Abschluss des Jobs können Sie auf die Attribute response.totalRows
und response.totalBytesProcessed
zugreifen. Es ist hilfreich, Millisekunden in Sekunden und Byte in Gigabyte umzurechnen, wie im folgenden Codebeispiel gezeigt.
function updateStatus(response){
if(response.statistics){
let durationMs = response.statistics.endTime - response.statistics.startTime;
let durationS = durationMs/1000;
let suffix = (durationS ==1) ? '':'s';
let durationTd = document.getElementById("duration");
durationTd.innerHTML = durationS + ' second' + suffix;
}
if(response.totalRows){
let rowsTd = document.getElementById("rowCount");
rowsTd.innerHTML = response.totalRows;
}
if(response.totalBytesProcessed){
let bytesTd = document.getElementById("bytes");
bytesTd.innerHTML = (response.totalBytesProcessed/1073741824) + ' GB';
}
}
Rufen Sie diese Methode auf, wenn eine Antwort auf einen checkJobStatus()
-Aufruf erfolgt und die Abfrageergebnisse abgerufen werden. Beispiel:
// Poll a job to see if it has finished executing.
function checkJobStatus(jobId){
let request = gapi.client.bigquery.jobs.get({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response => {
//Show progress to the user
updateStatus(response);
if (response.status.errorResult){
// Handle any errors.
console.log(response.status.error);
return;
}
if (response.status.state == 'DONE'){
// Get the results.
clearTimeout(jobCheckTimer);
getQueryResults(jobId);
return;
}
// Not finished, check again in a moment.
jobCheckTimer = setTimeout(checkJobStatus, 500, [jobId]);
});
}
// When a BigQuery job has completed, fetch the results.
function getQueryResults(jobId){
let request = gapi.client.bigquery.jobs.getQueryResults({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response => {
doHeatMap(response.result.rows);
updateStatus(response);
})
}
Wenn Sie die animierte Grafik ein- oder ausblenden möchten, fügen Sie eine Funktion hinzu, mit der sich ihre Sichtbarkeit steuern lässt. Diese Funktion ändert die Deckkraft eines beliebigen HTML-DOM-Elements, das an sie übergeben wird.
function fadeToggle(obj){
if(obj.style.opacity==1){
obj.style.opacity = 0;
setTimeout(() => {obj.style.zIndex = -1000;}, 1000);
} else {
obj.style.zIndex = 1000;
obj.style.opacity = 1;
}
}
Rufen Sie diese Methode schließlich vor der Verarbeitung einer Abfrage und nachdem das Abfrageergebnis von BigQuery zurückgegeben wurde auf.
Mit diesem Code wird die Funktion fadeToggle
aufgerufen, wenn der Nutzer das Zeichnen eines Rechtecks abgeschlossen hat.
drawingManager.addListener('rectanglecomplete', rectangle => {
//show an animation to indicate that something is happening.
fadeToggle(document.getElementById('spinner'));
rectangleQuery(rectangle.getBounds());
});
Wenn die Antwort auf die Anfrage eingegangen ist, rufen Sie fadeToggle()
noch einmal auf, um die animierte Grafik auszublenden.
// When a BigQuery job has completed, fetch the results.
function getQueryResults(jobId){
let request = gapi.client.bigquery.jobs.getQueryResults({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response => {
doHeatMap(response.result.rows);
//hide the animation.
fadeToggle(document.getElementById('spinner'));
updateStatus(response);
})
}
Die Seite sollte in etwa so aussehen.
Das vollständige Beispiel finden Sie in step8/map.html.
14. Wichtige Punkte
Zu viele Markierungen
Wenn Sie mit sehr großen Tabellen arbeiten, gibt Ihre Abfrage möglicherweise zu viele Zeilen zurück, um diese effizient auf einer Karte anzuzeigen. Sie können die Ergebnisse eingrenzen, indem Sie eine WHERE
-Klausel oder eine LIMIT
-Anweisung hinzufügen.
Wenn Sie viele Markierungen zeichnen, kann die Karte unleserlich werden. Verwenden Sie eine HeatmapLayer
, um die Dichte darzustellen, oder gruppieren Sie Markierungen, um mit einem einzelnen Symbol pro Cluster anzugeben, wo sich viele Datenpunkte befinden. Weitere Informationen finden Sie in unserem Marker-Clustering-Tutorial.
Abfragen optimieren
BigQuery scannt die gesamte Tabelle bei jeder Abfrage. Wählen Sie nur die Spalten aus, die Sie für Ihre Abfrage benötigen, um das BigQuery-Kontingent optimal zu nutzen.
Abfragen werden schneller ausgeführt, wenn Sie Breiten- und Längengrad als Gleitkommazahlen statt als Strings speichern.
Interessante Ergebnisse exportieren
Für die Beispiele hier muss der Endnutzer für die BigQuery-Tabelle authentifiziert sein. Das ist nicht für jeden Anwendungsfall geeignet. Wenn Sie interessante Muster gefunden haben, können Sie diese einfacher mit einem größeren Publikum teilen, indem Sie die Ergebnisse aus BigQuery exportieren und mit der Google Maps Data Layer ein statisches Dataset erstellen.
Das Kleingedruckte
Beachten Sie die Nutzungsbedingungen für die Google Maps Platform. Weitere Informationen zu den Preisen für die Google Maps Platform finden Sie in der Onlinedokumentation.
Mehr Daten nutzen
In BigQuery gibt es eine Reihe öffentlicher Datasets mit Breiten- und Längengradspalten, z. B. die NYC Taxi-Datasets von 2009 bis 2016, die Uber- und Lyft-Fahrtdaten für New York City und das GDELT-Dataset.
15. Glückwunsch!
Wir hoffen, dass Sie so schnell mit einigen geografischen Abfragen für BigQuery-Tabellen beginnen können, um Muster zu erkennen und auf einer Google-Karte zu visualisieren. Viel Spaß beim Erstellen von Karten!
Nächste Schritte
Wenn Sie mehr über die Google Maps Platform oder BigQuery erfahren möchten, sehen Sie sich die folgenden Vorschläge an.
Weitere Informationen zum serverlosen Data-Warehouse-Dienst von Google im Petabyte-Bereich finden Sie unter Was ist BigQuery?.
Anleitung zum Erstellen einer einfachen Anwendung mit der BigQuery API
Weitere Informationen zum Aktivieren der Nutzerinteraktion zum Zeichnen von Formen auf einer Google-Karte finden Sie im Entwicklerleitfaden für die Drawing-Bibliothek.
Weitere Möglichkeiten zum Visualisieren von Daten auf einer Google-Karte
Im Startleitfaden für die Javascript Client API finden Sie Informationen zu den grundlegenden Konzepten für den Zugriff auf andere Google APIs über die Client API.