Standortdaten in BigQuery mit der Google Maps Platform abfragen und visualisieren (JavaScript)

Standortdaten in BigQuery mit der Google Maps Platform abfragen und visualisieren (JavaScript)

Informationen zu diesem Codelab

subjectZuletzt aktualisiert: Dez. 3, 2021
account_circleVerfasst von Google Maps Platform Team

1. Übersicht

Karten können ein leistungsstarkes Tool sein, wenn Sie die Muster in einem Datensatz visualisieren, die sich auf den Standort beziehen. Diese Beziehung kann der Name eines Ortes, ein bestimmter Breiten- und Längengradwert oder der Name eines Bereichs mit einer bestimmten Grenze wie einem Volkszählungsgebiet oder einer Postleitzahl sein.

Wenn diese Datensätze sehr groß werden, können sie mit herkömmlichen Tools schwer abgefragt und visualisiert werden. Wenn Sie die Daten mit Google BigQuery abfragen, können Sie mit der Google Maps API die Abfrage konstruieren und die Ausgabe visualisieren, ohne dass Sie ein System verwalten müssen, das sehr große Datasets speichert. Dazu können Sie schnell geografische Muster in Ihren Daten untersuchen.

Aufgaben

In diesem Codelab lernen Sie, einige Abfragen zu erstellen und auszuführen, die standortbasierte Informationen über sehr große öffentliche Datasets mit BigQuery liefern. Außerdem erstellen Sie mit der Google Maps Platform JavaScript API eine Webseite, die eine Karte lädt. Anschließend werden mit der Google APIs-Clientbibliothek für JavaScript und der BigQuery API räumliche Abfragen für dieselben sehr großen öffentlichen Datasets ausgeführt und visualisiert.

Lerninhalte

  • Abfragen von Standort-Datasets im Petabytebereich in Sekunden mit BigQuery durchführen, mit SQL-Abfragen, benutzerdefinierten Funktionen und der BigQuery API
  • Mit der Google Maps Platform Google Maps-Karten auf einer Webseite einfügen und Nutzern das Zeichnen von Formen auf ihr erleichtern
  • Wie Sie Abfragen für große Datensätze auf einer Google Maps-Karte visualisieren können, z. B. im Beispiel unten, das die Dichte von Taxipunkten im Jahr 2016 auf Reisen aus dem Häuserblock um das Empire State Building veranschaulicht

Screenshot 2017-05-09 um 11.01.12 AM.png

Voraussetzungen

  • Grundkenntnisse in HTML, CSS, JavaScript, SQL und Chrome-Entwicklertools
  • Ein moderner Webbrowser, z. B. aktuelle Versionen von Chrome, Firefox, Safari oder Edge.
  • Texteditor oder IDE deiner Wahl

Die Technologie

BigQuery

BigQuery ist der Datenanalysedienst von Google für sehr große Datasets. Es verfügt über eine RESTful API und unterstützt Abfragen, die in SQL geschrieben werden. Wenn Sie Daten mit Breiten- und Längengraden haben, können diese zum Abfragen Ihrer Daten nach Standort verwendet werden. Der Vorteil ist, dass Sie sehr große Datasets untersuchen können, um sich die Muster anzusehen, ohne eine Server- oder Datenbankinfrastruktur verwalten zu müssen. Sie erhalten in wenigen Sekunden Antworten auf Ihre Fragen, unabhängig davon, wie groß Ihre Tabellen mit der umfangreichen Skalierbarkeit und verwalteten Infrastruktur von BigQuery sind.

Google Maps Platform

Die Google Maps Platform bietet programmatischen Zugriff auf Karten-, Orts- und Routendaten von Google. Derzeit werden die Inhalte von über 2 Millionen Websites und Apps verwendet, um Nutzern eingebettete Karten und standortbasierte Suchanfragen bereitzustellen.

Mit der Google Maps Platform JavaScript API-Zeichnungsebene können Sie Formen auf der Karte zeichnen. Diese können in das Eingabefeld konvertiert werden, um Abfragen für BigQuery-Tabellen auszuführen, in denen Breiten- und Längengradwerte in Spalten gespeichert sind.

Dazu benötigen Sie ein Google Cloud Platform-Projekt mit aktiviertem BigQuery und Maps APIs.

2. Einrichtung

Google-Konto

Wenn Sie noch kein Google-Konto haben (Gmail oder Google Apps), müssen Sie eines erstellen.

Projekt erstellen

Melden Sie sich unter console.cloud.google.com in der Google Cloud Platform Console an und erstellen Sie ein neues Projekt. Oben auf dem Bildschirm befindet sich das Drop-down-Menü „Projekt“:

f2a353c3301dc649.png

Wenn Sie auf dieses Drop-down-Menü klicken, erscheint ein Menüelement, mit dem Sie ein neues Projekt erstellen können:

56a42dfa7ac27a35.pngs

Geben Sie in das Feld, in dem Sie „einen neuen Namen für Ihr Projekt“ eingeben, einen Namen für das neue Projekt ein, z. B. „BigQuery Codelab“:

Codelab – Projekt erstellen (1).png

Es wird eine Projekt-ID generiert. Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig. Merken Sie sich Ihre Projekt-ID, da Sie sie später verwenden. Der Name oben ist bereits vergeben. Fügen Sie Ihre eigene Projekt-ID dort ein, wo Sie in diesem Codelab Ihre YOUR_PROJECT_ID sehen.

Abrechnung aktivieren

Verwenden Sie das Projekt, das Sie im vorherigen Schritt ausgewählt oder erstellt haben, um sich für BigQuery zu registrieren. Die Abrechnung für dieses Projekt muss aktiviert sein. Sobald die Abrechnung aktiviert ist, können Sie die BigQuery API aktivieren.

Wie Sie die Abrechnung aktivieren, hängt davon ab, ob Sie ein neues Projekt erstellen oder ob Sie die Abrechnung für ein vorhandenes Projekt wieder aktivieren.

Google bietet einen 12-monatigen kostenlosen Testzeitraum für bis zu 300 $, den Sie für dieses Codelab nutzen können. Weitere Informationen finden Sie unter https://cloud.google.com/free/.

Neue Projekte

Wenn Sie ein neues Projekt erstellen, werden Sie aufgefordert, das Abrechnungskonto auszuwählen, das Sie mit dem Projekt verknüpfen möchten. Wenn du nur ein Rechnungskonto hast, wird dieses Konto automatisch mit deinem Projekt verknüpft.

Wenn Sie kein Rechnungskonto haben, müssen Sie eines erstellen und die Abrechnung für Ihr Projekt aktivieren, bevor Sie viele Funktionen der Google Cloud Platform nutzen können. Wie Sie ein neues Rechnungskonto erstellen und die Abrechnung für Ihr Projekt aktivieren, erfahren Sie unter Neues Rechnungskonto erstellen.

Vorhandene Projekte

Wenn Sie die Abrechnung für ein Projekt vorübergehend deaktiviert haben, können Sie sie wieder aktivieren:

  1. Rufen Sie die Cloud Platform Console auf.
  2. Wählen Sie in der Projektliste das Projekt aus, für das die Abrechnung wieder aktiviert werden soll.
  3. Öffnen Sie das Menü links in der Konsole und wählen Sie Abrechnung Abrechnung aus. Sie werden aufgefordert, ein Rechnungskonto auszuwählen.
  4. Klicken Sie auf Konto festlegen.

Neues Rechnungskonto erstellen

So erstellen Sie ein neues Rechnungskonto:

  1. Rufe die Cloud Platform Console auf und melde dich an. Falls du noch kein Konto hast, registriere dich jetzt.
  2. Öffne das Menü auf der linken Seite der Konsole und wähle Abrechnung aus.Abrechnung
  3. Klicken Sie auf Neues Rechnungskonto. Hinweis: Wenn dies nicht Ihr erstes Rechnungskonto ist, müssen Sie zuerst die Rechnungskontoliste öffnen, indem Sie oben auf der Seite auf den Namen Ihres bestehenden Rechnungskontos und dann auf Rechnungskonten verwalten klicken.
  4. 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. Hinweis: Bei US-Konten können Sie den Steuerstatus nach Erstellung des Kontos nicht mehr ändern.
  5. 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 alternativen Zahlungsmethoden finden Sie unter Zahlungsmethode hinzufügen, entfernen oder aktualisieren.

Aktivieren der BigQuery-API

Rufen Sie zum Aktivieren der BigQuery API in Ihrem Projekt den BigQuery API-Seitenmarkt in der Konsole auf und klicken Sie auf die blaue Schaltfläche „Aktivieren'“.

3. Standortdaten in BigQuery abfragen

Es gibt drei Möglichkeiten, Standortdaten in BigQuery als Breiten- und Längengradwerte abzufragen.

  • Rectangle-Abfragen: Geben Sie den gewünschten Bereich als Abfrage an, um alle Zeilen innerhalb eines minimalen und maximalen Breiten- und Längengrads auszuwählen.
  • Umkreisfragen: Legen Sie den Radius fest, indem Sie einen Kreis um einen Punkt herum berechnen. Dazu verwenden Sie die Haversine-Formel und mathematische Funktionen, um die Form der Erde zu modellieren.
  • Polygonabfragen: Gib eine benutzerdefinierte Form an und verwende eine benutzerdefinierte Funktion, um die Punkt-Polygon-Logik auszudrücken, die für Tests erforderlich ist, wenn der Breiten- und Längengrad in die Form fallen.

Führen Sie als Erstes den Abfrageeditor im Abschnitt „BigQuery“ der Google Cloud Platform Console aus, um die folgenden Abfragen für die New Yorker Taxidaten auszuführen.

Standard-SQL und Legacy-SQL

BigQuery unterstützt zwei Versionen von SQL: Legacy-SQL und Standard-SQL. Letztere ist der ANSI-Standard 2011. In dieser Anleitung verwenden wir Standard-SQL, da hier die Standards besser eingehalten werden.

Wenn Sie Legacy-SQL im BigQuery-Editor ausführen möchten, gehen Sie so vor:

  1. Klicken Sie auf die Schaltfläche „Mehr“.
  2. Wählen Sie im Drop-down-Menü die Option „Abfrageeinstellungen“ aus.
  3. Wählen Sie unter „SQL-Dialekt“ das Optionsfeld „Alt“ aus.
  4. Klicken Sie auf die Schaltfläche „Speichern“.

Rectangle-Abfragen

Rectangle-Abfragen können ganz einfach in BigQuery erstellt werden. Fügen Sie einfach eine WHERE-Klausel hinzu, die die Ergebnisse auf Orte beschränkt, bei denen es sich um die Mindest- und Höchstwerte zwischen Breiten- und Längengrad handelt.

Sehen Sie sich das Beispiel unten in der BigQuery-Konsole an. Diese Abfrage beziehen sich auf einige durchschnittliche Fahrtstatistiken für Fahrten, die in einem rechteckigen Bereich begonnen haben, der Midtown und Lower Manhattan enthält. Es gibt zwei verschiedene Standorte, die Sie ausprobieren können. Entfernen Sie die Kommentare für die zweite WHERE-Klausel, um die Abfrage für Fahrten durchzuführen, die am Flughafen JFK gestartet wurden.

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 für die beiden Suchanfragen zeigen, dass es bei den beiden Orten große Unterschiede zwischen der durchschnittlichen Entfernung, dem Preis und der Trinkgelder gibt.

Manhattan

avg_tip

Durchschn. Preis

Durchschn. Entfernung

avg_tip_pc

avg_fare_Meile

2,52

12,03

9,97

22,39

5,97

BER

avg_tip

Durchschn. Preis

Durchschn. Entfernung

avg_tip_pc

avg_fare_Meile

9,22

48,49

41,19

22,48

4,36

Umkreisbezogene Abfragen

Radiusabfragen sind auch in SQL einfach zu konstruieren, wenn Sie sich mit Mathe auskennen. Mithilfe der Legacy-Mathefunktionen von BigQuery können Sie eine SQL-Abfrage mit der Haversine-Formel erstellen, mit der eine kreisförmige Fläche oder eine kugelförmige Oberfläche auf der Erdoberfläche geschätzt wird.

Hier sehen Sie eine BigQuery SQL-Beispielanweisung für eine Kreisabfrage mit einem Mittelpunkt von 40.73943, -73.99585 mit einem Radius von 0,1 km.

Der geschätzte Wert für die Entfernung ist in einem konstanten Wert von 111,045 Kilometern angegeben.

Dies 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

Die SQL-Formel für die Haversine-Formel wirkt kompliziert, Sie müssen aber nur die Koordinaten des Kreismittelpunkts sowie den Radius, das Projekt, den Datensatz und die Tabellennamen für BigQuery einfügen.

Hier sehen Sie eine Beispielabfrage, bei der einige durchschnittliche Fahrtstatistiken für Abholungen innerhalb von 100 m vom Empire State Building berechnet werden. Kopieren Sie diesen Code und fügen Sie ihn in die BigQuery-Webkonsole ein, um die Ergebnisse anzusehen. Ändern Sie den Breiten- und Längengrad mit anderen Regionen wie dem Standort in der Bronx.

#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 finden Sie unten. Wie Sie sehen, sind die durchschnittlichen Kosten pro 1 Meile und die durchschnittlichen Kosten pro 1 Meile (1,6 km), wenn der Fahrpreis im Preis mit durchschnittlichen Kosten pro Fahrt (Tene Kilometer) übereinstimmt.

Empire State Building:

avg_tip

Durchschn. Preis

Durchschn. Entfernung

avg_tip_pc

avg_fare_Meile

1.17

11,08

45,28

10,53

6,42

In Dortmund

avg_tip

Durchschn. Preis

Durchschn. Entfernung

avg_tip_pc

avg_fare_Meile

0,52

17,63

4,75

4,74

10.9

Polygonabfragen

SQL unterstützt keine Abfrage mit beliebigen anderen Formen als Rechtecken und Kreisen. BigQuery hat keinen nativen Geometriedaten- oder räumlichen Index. Wenn Sie also Abfragen mit Polygonformen ausführen möchten, benötigen Sie einen anderen Ansatz für einfache SQL-Abfragen. Ein Ansatz besteht darin, eine Geometriefunktion in JavaScript zu definieren und sie in BigQuery als benutzerdefinierte Funktion (UDF) auszuführen.

Viele Geometrievorgänge können in JavaScript geschrieben werden. Das erleichtert die Ausführung einer Abfrage und die Ausführung in einer BigQuery-Tabelle, die Breiten- und Längengradwerte enthält. Sie müssen das benutzerdefinierte Polygon über eine UDF übergeben und für jede Zeile einen Test durchführen. Dabei werden nur Zeilen zurückgegeben, bei denen der Längen- und der Breitengrad in das Polygon fällt. Weitere Informationen zu benutzerdefinierten Dimensionen finden Sie in der BigQuery-Referenz.

Point-in-Polygon-Algorithmus

Es gibt viele Möglichkeiten zu berechnen, ob ein Punkt in JavaScript in ein Polygon fällt. In diesem Beispiel handelt es sich um einen Port aus C einer bekannten Implementierung, bei dem ein Raytracing-Algorithmus verwendet wird, um zu bestimmen, ob sich ein Punkt innerhalb oder außerhalb eines Polygons befindet. Dabei wird erfasst, wie oft eine unendlich lange Linie die Grenze der Form überschreitet. Es sind nur wenige Codezeilen nötig:

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;
}

In JavaScript portieren

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 sein. Hier ein Beispiel: Fügen Sie die folgende SQL-Anweisung 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, ist der Standort wichtig für die Ergebnisdaten der Datensätze, doch wenn Sie nicht wissen, wo Sie Ihre Abfragen ausführen können, ist es schwierig, räumliche Muster anhand von SQL-Abfragen zu erkennen.

Wenn nur die Daten auf einer Karte dargestellt werden könnten und die Daten beliebige Bereiche von Interesse sind, können Sie sie erkunden. Mit den Google Maps APIs ist genau das möglich. Zuerst müssen Sie die Maps API aktivieren, eine einfache Webseite auf Ihrem lokalen Computer einrichten und Abfragen über die BigQuery API 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 erkennen. Dazu aktivieren Sie die Google Maps API und erstellen eine Webseite, die Abfragen von einer Karte an BigQuery sendet und die Ergebnisse dann auf der Karte zeichnet.

Maps JavaScript API aktivieren

Für dieses Codelab müssen Sie die Maps JavaScript API von Google Maps Platform in Ihrem Projekt aktivieren. Gehen Sie hierzu wie folgt vor:

  1. Gehen Sie in der Google Cloud Platform Console zum Marketplace.
  2. Suchen Sie im Marktplatz nach „Maps JavaScript API'“
  3. Klicken Sie in den Suchergebnissen auf die Kachel für die Maps JavaScript API.
  4. Klicken Sie auf die Schaltfläche „Aktivieren“

API-Schlüssel generieren.

Um Anfragen an die Google Maps Platform zu senden, müssen Sie einen API-Schlüssel generieren und mit allen Anfragen senden. So generieren Sie einen API-Schlüssel:

  1. Klicken Sie in der Google Cloud Platform Console auf das Hamburger-Menü, um die linke Navigationsleiste zu öffnen.
  2. Wähle 'APIs & Service' > 'Anmeldedaten' aus.
  3. Klicke auf die Schaltfläche „Anmeldedaten erstellen“ und wähle „API-Schlüssel“ aus.
  4. Neuen API-Schlüssel kopieren

Code herunterladen und einen 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. Dieser enthält einen Ordner für jeden Schritt dieses Codelabs sowie alle erforderlichen Ressourcen.

Die Ordner stepN enthalten den gewünschten Endstatus der einzelnen Schritte dieses Codelabs. Sie sind als Referenz verfügbar. Alle Coding-Vorgänge werden im Verzeichnis work ausgeführt.

Lokalen Webserver einrichten

Sie können Ihren eigenen Webserver zwar verwenden, dieses Codelab ist aber auf die Arbeit mit dem Chrome-Webserver ausgelegt. Wenn du sie noch nicht installiert hast, kannst du sie über den Chrome Web Store installieren.

Öffnen Sie die App, nachdem Sie sie installiert haben. Gehen Sie in Chrome so vor:

  1. Chrome öffnen
  2. Geben Sie oben „chrome://apps“ in die Adressleiste ein.
  3. Drücken Sie die Eingabetaste.
  4. Klicken Sie im Fenster, das daraufhin geöffnet wird, auf das Webserver-Symbol. Sie können auch mit der rechten Maustaste auf eine App klicken, um sie in einem normalen oder angepinnten Tab, einem Vollbildmodus oder einem neuen Fenster zu öffnen. a3ed00e79b8bfee7.pngs Im folgenden Dialogfeld können Sie den lokalen Webserver konfigurieren: 81b6151c3f60c948
  5. Klicken Sie auf „Ordner auswählen“ &#39 und wählen Sie den Speicherort aus, an den Sie die Codelab-Beispieldateien heruntergeladen haben
  6. Klicken Sie im Abschnitt „Optionen“ das Kästchen neben „Index automatisch anzeigen.html': 17f4913500faa86f“ an.
  7. Bewegen Sie den Schieberegler mit der Bezeichnung „Webserver: STARTED' nach links und dann wieder nach rechts, um den Vorgang zu beenden. Starten Sie dann den Webserver neu.

a5d554d0d4a91851

5. Karten- und Zeichentools werden geladen

Einfache Kartenseite erstellen

Beginnen Sie mit einer einfachen HTML-Seite, die eine Google Maps-Karte mithilfe der Maps JavaScript API lädt und JavaScript-Zeilen enthält. Der Code aus dem einfachen Kartenbeispiel der Google Maps Platform ist ein guter Ausgangspunkt. Sie wurden hier für das Kopieren und Einfügen in den Texteditor oder die IDE Ihrer Wahl reproduziert. Sie finden sie auch, indem Sie in dem heruntergeladenen Repository index.html öffnen.

  1. Kopieren Sie index.html in den Ordner work in Ihrer lokalen Kopie des Repositorys
  2. Kopieren Sie den Ordner „img/“ in den Ordner „work/“ in Ihrer lokalen Kopie des Repositorys.
  3. Öffne Work/index.html in deinem Texteditor oder deiner IDE
  4. Ersetzen Sie dabei 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>
  1. Öffnen Sie localhost:<port>/work in Ihrem Browser, wobei port die Portnummer ist, die in der Konfiguration Ihres lokalen Webservers angegeben ist. Der Standardport ist 8887. Sie sollten Ihre ersten Karten sehen.

Wenn Sie im Browser eine Fehlermeldung erhalten, prüfen Sie, ob der API-Schlüssel korrekt ist und der lokale Webserver aktiv ist.

Standardposition und Zoomstufe ändern

Der Code für die Position und die Zoomstufe befindet sich in den Zeilen 27 und 28 der Datei „index.html“ und ist derzeit 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>

Diese Anleitung funktioniert mit BigQuery-Taxidaten für New York. Sie werden den Karteninitialisierungscode also so ändern, dass ein Ort in New York mit einer angemessenen Zoomstufe zentriert wird – 13 oder 14 sollte gut funktionieren.

Aktualisieren Sie dazu den Codeblock oben auf dem Kartenrand, um die Karte im Empire State Building zu zentrieren, und stellen Sie die Vergrößerungsstufe auf 14 ein:

<script>
      let map
;
     
function initMap() {
        map
= new google.maps.Map(document.getElementById('map'), {
          center
: {lat: 40.7484405, lng: -73.9878531},
          zoom
: 14
       
});
     
}
</script>

Aktualisiere als Nächstes die Karte in deinem Browser, um die Ergebnisse zu sehen.

Zeichnungs- und Visualisierungsbibliotheken laden

Um Zeichenfunktionen für Ihre Karte zu implementieren, ändern Sie das Skript, mit dem die Maps JavaScript API geladen wird. Hierfür fügen Sie einen optionalen Parameter hinzu, der die Google Maps Platform anweist, die Zeichenbibliothek zu aktivieren.

In diesem Codelab wird auch das HeatmapLayer-Element verwendet, sodass Sie auch das Skript aktualisieren, um die Visualisierungsbibliothek anzufordern. Füge dazu den Parameter libraries hinzu und gib die Bibliotheken visualization und drawing als kommagetrennte 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>

Zeichnungen-Manager hinzufügen

Wenn du von Nutzern gezeichnete Formen als Eingabe für eine Abfrage verwenden möchtest, füge der Karte das DrawingManager-Objekt hinzu, während die Tools Circle, Rectangle und Polygon aktiviert sind.

Es empfiehlt sich, den gesamten Einrichtungscode von DrawingManager in einer neuen Funktion zu platzieren. Führe in der Kopie von index.html also folgende Schritte aus:

  1. Füge eine Funktion namens setUpDrawingTools() mit dem folgenden Code hinzu, um DrawingManager zu erstellen, und setze ihre map-Property so, dass sie auf das Kartenobjekt auf der Seite verweist.

Mit den Optionen, die an google.maps.drawing.DrawingManager(options) weitergegeben werden, wird der Standardformtyp für die Form und die Anzeigeoptionen für gezeichnete Formen festgelegt. Bei der Auswahl von Gebieten, auf denen Karten als Anfragen gesendet werden sollen, müssen die Formen eine Deckkraft von null haben. Weitere Informationen zu verfügbaren Optionen finden Sie unter Zeichnungsmanageroptionen.

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);
}
  1. Rufe setUpDrawingTools() nach der Erstellung des Kartenobjekts in deiner initMap()-Funktion auf
function initMap() {
  map
= new google.maps.Map(document.getElementById('map'), {
    center
: {lat: 40.744593, lng: -73.990370}, // Manhattan, New York.
    zoom
: 12
 
});

  setUpDrawingTools
();
}
  1. Aktualisieren Sie die Datei „index.html“ und prüfen Sie, ob die Zeichentools sichtbar sind. Prüfen Sie außerdem, ob Sie sie zum Zeichnen von Kreisen, Rechtecken und Polygonformen verwenden können.

Sie können klicken und ziehen, um Kreise und Rechtecke zu zeichnen, aber Polygone müssen gezeichnet werden. Klicken Sie dazu auf jeden Eckpunkt und klicken Sie doppelt, um die Form fertigzustellen.

Zeichenereignisse verarbeiten

Sie benötigen etwas Code, um die Ereignisse zu verarbeiten, die ausgelöst werden, wenn ein Nutzer eine Form zeichnet, genau wie Sie die Koordinaten der gezeichneten Formen benötigen, um SQL-Abfragen zu erstellen.

Wir fügen Code dafür in einem späteren Schritt hinzu. Vorerst werden jedoch drei leere Event-Handler aufgeführt, um die Ereignisse rectanglecomplete, circlecomplete und polygoncomplete zu verarbeiten. Die Handler müssen in dieser Phase keinen Code ausführen.

Fügen Sie unten in der Funktion setUpDrawingTools() Folgendes ein:

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.
});

Sie finden ein funktionierendes Beispiel für diesen Code in Ihrer lokalen Kopie des Repositorys im Ordner step2: step2/map.html.

6. BigQuery Client API verwenden

Mit der Google BigQuery Client API vermeiden Sie das Schreiben von Boilerplate-Code, 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-Clientbibliothek für 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 mit BigQuery zu interagieren.

Google Client API für JavaScript hinzufügen

Sie verwenden die Google Client API für JavaScript, um Abfragen in BigQuery auszuführen. Lade die API mit einem <script>-Tag wie diesem in deiner Kopie von index.html in deinem work-Ordner. Füge das Tag direkt unter dem Tag <script> ein, mit dem die Maps API geladen wird:

<script src='https://apis.google.com/js/client.js'></script>

Nach dem Laden der Google Client API autorisieren Sie den Nutzer, auf die Daten in BigQuery zuzugreifen. 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

  1. Wählen Sie in der Google Cloud Console über das Navigationsmenü die Option APIs &AMP; Dienste > Anmeldedaten aus.

Bevor Sie Ihre Anmeldedaten einrichten können, müssen Sie eine Konfiguration für den Autorisierungsbildschirm hinzufügen, den ein Endnutzer Ihrer Anwendung sieht, wenn er Ihre App autorisiert, auf Daten von BigQuery zuzugreifen.

Klicken Sie dazu auf den Tab OAuth-Zustimmungsbildschirm. 2. Sie müssen die BigQuery-API zu den Bereichen für dieses Token hinzufügen. Klicken Sie im Abschnitt „Bereiche für Google APIs“ auf die Schaltfläche Umfang hinzufügen. 3. Klicken Sie in der Liste auf das Kästchen neben dem Eintrag Big Query API mit dem Umfang ../auth/bigquery. 4. Klicken Sie auf Add (Hinzufügen). 5. Geben Sie in das Feld „Anwendungsname' einen Namen ein. 6. Klicken Sie noch einmal auf Speichern, um die Einstellungen zu bestätigen. 7. Als Nächstes erstellen Sie die OAuth-Client-ID. Klicken Sie dazu auf Anmeldedaten erstellen:

4d18a965fc760e39

  1. Klicken Sie im Drop-down-Menü auf OAuth-Client-ID. 1f8b36a1c27c75f0
  2. Wählen Sie unter „Anwendungstyp“ die Option Webanwendung aus.
  3. Geben Sie in das Feld „Anwendungsname“ einen Namen für Ihr Projekt ein. Beispiel: BigQuery und Maps&quot.
  4. Geben Sie unter Beschränkungen im Feld „Autorisierte JavaScript-Quellen“ die URL von „localhost“ ein, einschließlich der Portnummern. Beispiel: http://localhost:8887
  1. Klicken Sie auf Create (Erstellen).

In einem Pop-up werden die Client-ID und der Clientschlüssel angezeigt. Sie benötigen die Client-ID für die Authentifizierung bei BigQuery. Kopieren Sie es und fügen Sie es als neue globale JavaScript-Variable namens clientId in work/index.html ein.

let clientId = 'YOUR_CLIENT_ID';

7. Autorisierung und Initialisierung

Ihre Webseite muss den Nutzer autorisieren, auf BigQuery zuzugreifen, bevor er die Karte initialisiert. In diesem Beispiel verwenden wir OAuth 2.0, wie im Abschnitt zur Autorisierung der JavaScript Client API-Dokumentation beschrieben. Zum Senden von Abfragen müssen Sie die OAuth-Client-ID und Ihre Projekt-ID verwenden.

Wenn die Google Client API auf der Webseite geladen wird, müssen Sie Folgendes tun:

  • Autorisieren Sie den Nutzer.
  • Wenn die Autorisierung erfolgt ist, laden Sie die BigQuery API.
  • Laden und initialisieren Sie die Karte.

Ein Beispiel dafür, wie die fertige HTML-Seite aussehen würde, finden Sie unter step3/map.html.

Nutzer autorisieren

Der Endnutzer der Anwendung muss die Anwendung autorisieren, in ihrem Namen auf Daten in BigQuery zuzugreifen. Die OAuth-Logik wird von der Google Client API für JavaScript verarbeitet.

In einer Praxisanwendung haben Sie viele Möglichkeiten, den Autorisierungsschritt zu integrieren.

Du kannst beispielsweise authorize() über ein UI-Element wie eine Schaltfläche aufrufen oder den Vorgang beim Laden der Seite. Hier haben wir ausgewählt, dass der Nutzer nach dem Laden der Google Client API für JavaScript autorisiert wird. Das erfolgt über eine Callback-Funktion in der Methode gapi.load().

Schreiben Sie unmittelbar nach dem <script>-Tag, das die Google Client API für JavaScript lädt, Code, damit sowohl die Clientbibliothek als auch das Authentifizierungsmodul geladen werden. So können wir den Nutzer sofort authentifizieren.

<script src='https://apis.google.com/js/client.js'></script>
<script type='text/javascript'>
  gapi
.load('client:auth', authorize);
</script>

Bei Autorisierung die BigQuery API laden

Nachdem der Nutzer autorisiert wurde, laden Sie die BigQuery API.

Rufen Sie zuerst gapi.auth.authorize() mit der clientId-Variable auf, die Sie im vorherigen Schritt hinzugefügt haben. Verarbeiten Sie die Antwort in einer Callback-Funktion mit dem Namen handleAuthResult.

Mit dem Parameter immediate wird festgelegt, ob dem Nutzer ein Pop-up angezeigt wird. Setzen Sie ihn auf true, um das Pop-up für die Autorisierung zu unterdrücken, wenn der Nutzer bereits autorisiert ist.

Fügen Sie Ihrer Seite die Funktion „handleAuthResult()“ hinzu. Die Funktion muss einen authresult-Parameter verwenden, mit dem Sie den Logikfluss steuern können, je nachdem, ob der Nutzer autorisiert wurde oder nicht.

Fügen Sie außerdem eine Funktion namens loadApi hinzu, um die BigQuery API zu laden, wenn der Nutzer autorisiert wurde.

Füge der Logik die handleAuthResult()-Funktion hinzu, um loadApi() aufzurufen, wenn ein authResult-Objekt an die Funktion übergeben wird und wenn die error-Property 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 initialisieren Sie die Karte. Du musst dafür die Reihenfolge der Logik ändern. Derzeit wird der Container initialisiert, wenn das Maps API-JavaScript geladen wurde.

Rufen Sie dazu die Funktion initMap() aus der Methode then() nach der Methode load() für das Objekt gapi.client 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, jedoch werden möglicherweise nicht sofort Antworten zurückgegeben. 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.

Den vollständigen Code für diesen Schritt finden Sie unter step4/map.html.

Anfrage senden

Fügen Sie work/index.html eine JavaScript-Funktion hinzu, um eine Abfrage mit der API zu senden, sowie einige Variablen, in denen die Werte des BigQuery-Datasets und -Projekts mit der abzufragenden Tabelle und die Projekt-ID gespeichert werden.

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 Sie den Status eines Jobs regelmäßig mithilfe der API-Methode get und der von der ursprünglichen Abfrage zurückgegebenen jobId prüfen können. Hier sehen Sie 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]);    
 
});
}

Ändere die sendQuery-Methode, um die checkJobStatus()-Methode als Callback im request.execute()-Aufruf aufzurufen. Übergeben Sie die Job-ID an checkJobStatus. Dies wird vom Antwortobjekt als jobReference.jobId angezeigt.

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));
}

Ergebnisse einer Abfrage abrufen

Wenn Sie die Ergebnisse einer Abfrage beenden möchten, verwenden Sie den API-Aufruf jobs.getQueryResults. Füge deiner Seite die Funktion 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, räumliche Abfragen für Daten in BigQuery mit SQL auszuführen:

  • Auswählen nach Rechteck (auch als Begrenzungsrahmen bezeichnet)
  • nach Radius auswählen und
  • mit der leistungsstarken Funktion Benutzerdefinierte Funktionen

Beispiele für Begrenzungsrahmen- und Radiusabfragen finden Sie im Abschnitt „Mathematische Funktionen“ der Legacy-SQL-Referenz für BigQuery unter „Erweiterte Beispiele'“.

Für Anfragen zu Begrenzungsrahmen und Umkreis können Sie die BigQuery API-Methode query aufrufen. Erstelle die SQL-Anweisung für jede Abfrage und übergib sie an die sendQuery-Funktion, die du im vorherigen Schritt erstellt hast.

Ein funktionierendes Beispiel für den Code für diesen Schritt finden Sie unter step4/map.html.

Rectangle-Abfragen

Die einfachste Möglichkeit, BigQuery-Daten auf einer Karte darzustellen, besteht darin, alle Zeilen anzufordern, in denen die Breiten- und Längengrade in ein Rechteck fallen, wobei ein kleinerer und größerer Wert als Vergleich verwendet wird. Dies kann die aktuelle Kartenansicht oder eine auf der Karte dargestellte Form sein.

Wenn du eine vom Nutzer gezeichnete Form verwenden möchtest, ändere den Code in index.html, um das Zeichenereignis zu verarbeiten, das ausgelöst wird, wenn ein Rechteck abgeschlossen ist. In diesem Beispiel verwendet der Code getBounds() für das Rechteckobjekt, um ein Objekt abzurufen, das den Umfang des Rechtecks in Kartenkoordinaten darstellt. Anschließend übergibt es eine Funktion namens rectangleQuery:

drawingManager.addListener('rectanglecomplete', rectangle => rectangleQuery(rectangle.getBounds()));

Bei der rectangleQuery-Funktion müssen dazu nur die Koordinaten oben rechts (Nordost) und unten links (Südwest) verwendet werden, um einen Vergleich zu erstellen, der kleiner als oder größer als jede Zeile in Ihrer BigQuery-Tabelle ist. Hier sehen Sie ein Beispiel für eine Abfrage mit einer Tabelle, die die Spalten 'pickup_latitude' und 'pickup_longitude' enthält, in denen die Standortwerte gespeichert sind.

BigQuery-Tabelle angeben

Zum Abfragen einer Tabelle mit der BigQuery API müssen Sie den Namen der Tabelle in Ihrer SQL-Abfrage in voll 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-Taxifahrten. Wenn Sie sie sehen möchten, rufen Sie die BigQuery-Webkonsole auf und maximieren Sie den Menüpunkt „Öffentliche Datasets“. Suchen Sie das Dataset new_york und maximieren Sie es, um die Tabellen einzublenden. Wählen Sie die Tabelle der gelben Taxifahrten aus: bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2016.

Projekt-ID angeben

Im API-Aufruf müssen Sie zu Abrechnungszwecken den Namen Ihres Google Cloud Platform-Projekts angeben. In diesem Codelab ist dies nicht dasselbe Projekt wie das Projekt, das die Tabelle enthält. Wenn Sie mit einer Tabelle gearbeitet haben, die Sie in Ihrem eigenen Projekt durch Hochladen von Daten erstellt hatten, würde diese Projekt-ID mit der in Ihrer SQL-Anweisung übereinstimmen.

Fügen Sie Ihrem Code JavaScript-Variablen hinzu, die Verweise auf das öffentliche Dataset-Projekt mit der abgefragten Tabelle sowie den Tabellennamen und Dataset-Namen enthalten. Sie benötigen auch eine separate Variable, um auf Ihre eigene Abrechnungsprojekt-ID zu verweisen.

Fügen Sie Ihrer Kopie der Datei „index.html“ die globalen JavaScript-Variablen billingProjectId, publicProjectId, datasetId und tableName hinzu.

Initialisiere die Variablen 'publicProjectId', 'datasetId' und 'tableName' mit den Details aus dem BigQuery-Projekt für öffentliche Datensätze. Initialisieren Sie billingProjectId mit Ihrer eigenen Projekt-ID (der Projekt-ID, die Sie zuvor in diesem Codelab 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 dem Code jetzt zwei Funktionen hinzu, um den SQL-Code zu generieren und die Abfrage mit der Funktion sendQuery zu senden, die Sie im vorherigen Schritt erstellt haben.

Die erste Funktion sollte rectangleSQL() nennen. Sie muss zwei Argumente akzeptieren, ein Paar von google.Maps.LatLng-Objekten, die die Ecken des Rechtecks in Kartenkoordinaten darstellen.

Die zweite Funktion sollte rectangleQuery() nennen. 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;
}

Jetzt haben Sie genügend Code, um eine Abfrage an alle Zeilen zu senden, die von einem vom Nutzer gezeichneten Rechteck enthalten sind. Bevor wir weitere Abfragemethoden für Kreise und Freiformen hinzufügen, sehen wir uns an, wie wir mit den Daten umgehen, die von einer Abfrage zurückgegeben werden.

10. Antworten visualisieren

BigQuery-Tabellen können sehr groß sein – Petabyte an Daten. Sie können um Hunderttausende Zeilen pro Sekunde wachsen. Daher ist es wichtig, dass Sie versuchen, die Menge der zurückgegebenen Daten zu begrenzen, damit sie auf der Karte dargestellt werden kann. Das Zeichnen der Position jeder Zeile in einer sehr großen Ergebnismenge (Zehntausende Zeilen oder größer) führt zu einer unlesbaren Karte. Es gibt viele Methoden, um die Standorte in der SQL-Abfrage und auf der Karte zu aggregieren. Sie können die Ergebnisse, die von der Abfrage zurückgegeben werden, einschränken.

Den vollständigen Code für diesen Schritt finden Sie unter step5/map.html.

Ändern Sie die rectangleSQL()-Funktion so, dass die Antwort auf 10.000 Zeilen beschränkt ist, damit die an Ihre Webseite übertragenen Daten nicht zu groß für dieses Codelab sind. Im folgenden Beispiel wird die Variable in einer globalen Variablen namens recordLimit angegeben, sodass 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 kannst du die Standortdichte von Standorten visualisieren. Die Maps JavaScript API hat zu diesem Zweck eine HeatmapLayer-Klasse. Die HeatmapLayer verwendet ein Array mit Breiten- und Längengradkoordinaten, sodass die aus der Abfrage zurückgegebenen Zeilen in eine Heatmap umgewandelt werden können.

Übergeben Sie in der getQueryResultsFunktion das Array response.result.rowsan eine neue JavaScript-Funktion namens doHeatMap(), die eine Heatmap erstellt.

Jede Zeile hat die Eigenschaft f, ein Array mit Spalten. Jede Spalte enthält die Property v, die den Wert enthält.

Der Code muss als Schleife durch die Spalten in jeder Zeile geführt werden und die Werte extrahieren.

In der SQL-Abfrage haben Sie nur nach den Werten „Breitengrad“ und „Längengrad“ der Taxifahrer gesucht, sodass die Antwort nur zwei Spalten enthält.

Vergessen Sie nicht, setMap() in der Heatmap-Ebene aufzurufen, wenn Sie dem Array die Positionen zugewiesen haben. Dadurch wird sie 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);
}

Sie sollten nun Folgendes können:

  • Seite öffnen und für BigQuery autorisieren
  • Rechteck irgendwo in NYC zeichnen
  • Die Ergebnisse der Abfrageergebnisse werden als Heatmap dargestellt.

Hier ist ein Beispiel für das Ergebnis einer rechteckigen Abfrage für die NYC-Gelbe Taxidaten im Jahr 2016 als Heatmap. Das ist die Verteilung der Abholungen um das Empire State Building an einem Samstag im Juli:

7b1face0e7c71c78.pngs

11. Nach Umkreis um einen Punkt abfragen

Umkreisbezogene Abfragen sind sich ähnlich. Mit den alten SQL-Funktionen in BigQuery können Sie eine SQL-Abfrage mit der Haversine-Formel erstellen, mit der ein Kreisbereich auf der Erdoberfläche geschätzt wird.

Mit der gleichen Methode für Rechtecke können Sie ein OverlayComplete-Ereignis verarbeiten, um den Mittelpunkt und den Radius eines vom Nutzer gezeichneten Kreises zu erhalten. So können Sie den SQL-Code für die Abfrage auf dieselbe Weise erstellen.

Ein funktionierendes Beispiel für den Code dieses Schritts finden Sie im Code-Repository als step6/map.html.

drawingManager.addListener('circlecomplete', circle => circleQuery(circle));

Fügen Sie in die Kopie von „index.html“ zwei neue leere Funktionen ein: circleQuery() und haversineSQL().

Fügen Sie dann einen circlecomplete-Ereignis-Handler hinzu, der den Mittelpunkt und den Radius in einer neuen Funktion namens circleQuery(). übergibt

Die Funktion circleQuery() ruft haversineSQL() auf, um den SQL-Code für die Abfrage zu erstellen, und sendet dann die Abfrage, indem die Funktion sendQuery() wie im folgenden Beispielcode aufgerufen wird.

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 Code oben hinzu und versuchen Sie es mit dem Kreistool, um einen Kartenbereich auszuwählen. Das Ergebnis sollte in etwa so aussehen:

845418166b7cc7a3

12. Beliebige Formen abfragen

Zusammenfassung: SQL unterstützt keine Abfrage mit beliebigen Formen außer Rechtecken und Kreisen. BigQuery hat keinen nativen Geometriedaten. Daher benötigen Sie einen anderen Ansatz für einfache SQL-Abfragen, um Abfragen mit Polygonformen auszuführen.

Eine sehr leistungsfähige BigQuery-Funktion, die dafür verwendet werden kann, ist benutzerdefinierte Funktionen. Hiermit wird JavaScript in einer SQL-Abfrage ausgeführt.

Der funktionierende Code für diesen Schritt finden Sie unter step7/map.html.

UIs in der BigQuery API

Der BigQuery API-Ansatz für SaaS unterscheidet sich geringfügig von der Webkonsole: Sie müssen den jobs.insert method aufrufen.

Bei Standard-SQL-Abfragen über die API ist nur eine einzige SQL-Anweisung erforderlich, um eine benutzerdefinierte Funktion zu verwenden. Der Wert für useLegacySql muss auf false festgelegt sein. Das JavaScript-Beispiel unten zeigt eine Funktion, die ein Anfrageobjekt zum Einfügen eines neuen Jobs erstellt und sendet, in diesem Fall eine Abfrage mit einer benutzerdefinierten Funktion.

Ein funktionierendes Beispiel für diesen Ansatz ist 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;
}

Es gibt zwei Dinge: Zuerst wird mit dem Code die Anweisung CREATE TEMPORARY FUNCTION erstellt, die den JavaScript-Code einschließt, mit dem sich festlegen lässt, dass sich ein bestimmter Punkt in einem Polygon befindet. Die Polygonkoordinaten werden mit dem Aufruf der Methode JSON.stringify(poly) eingefügt,um ein JavaScript-Array aus x- und y-Koordinaten in einen String umzuwandeln. Das Polygonobjekt wird als Argument an die Funktion übergeben, mit der SQL erstellt wird.

Zweitens erstellt der Code die SQL-Hauptanweisung SELECT. Die UDF wird in diesem Beispiel im WHERE-Ausdruck aufgerufen.

In Maps API einbinden

Für die Verwendung mit der Maps API-Zeichnungsbibliothek 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 aus Längen- und Breitengraden zu erhalten:

drawingManager.addListener('polygoncomplete', polygon => {
  let path
= polygon.getPaths().getAt(0);
  let queryPolygon
= path.map(element => {
   
return [element.lng(), element.lat()];
 
});
  polygonQuery
(queryPolygon);
});

Mit der polygonQuery-Funktion können dann die UDF-JavaScript-Funktionen als String sowie die SQL-Anweisung erstellt werden, die die UDF-Funktion aufruft.

Ein funktionierendes Beispiel finden Sie unter „step7/map.html“.

Beispielausgabe

Hier ein Beispiel für die Abfrage von Abholungen aus den 2016 NYC TLC Yellow Taxi-Daten in BigQuery mithilfe eines selbst gewählten Polygons, wobei die ausgewählten Daten als Heatmap gezeichnet werden.

Screenshot 2017-05-09 um 10.00.48.png

13. Weitere Fragen

Hier finden Sie einige Vorschläge zur Erweiterung dieses Codelabs, damit Sie sich weitere Aspekte der Daten ansehen können. Ein funktionierendes Beispiel für diese Ideen finden Sie im Code-Repository unter step8/map.html.

Zuordnungsabbrüche

Bis jetzt haben wir nur Abholstationen zugeordnet. Wenn Sie die Spalten dropoff_latitude und dropoff_longitude anfordern und den Heatmap-Code ändern, um diese stattdessen darzustellen, können Sie die Ziele von Taxifahrten sehen, die an einem bestimmten Ort gestartet wurden.

Beispiel: Lassen Sie uns wissen, wo Taxis oft absetzen, wenn sie einen Abholdienst um das Empire State Building anfordern.

Ändern Sie den Code für die SQL-Anweisung in polygonSql(), wenn Sie diese Spalten zusätzlich zum Abholort anfordern möchten.

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;
}

Für die Funktion doHeatMap können Sie stattdessen die Drop-down-Werte verwenden. Das Ergebnisobjekt enthält ein Schema, das überprüft werden kann, um die Position dieser Spalten im Array zu finden. In diesem Fall befinden sie sich an den Indexpositionen 2 und 3. Diese Indexe können aus einer Variablen gelesen werden, um die Verwaltung des Codes zu erleichtern. NB: Die maxIntensity der Heatmap wird auf eine Dichte von maximal 20 Abbrüchen pro Pixel festgelegt.

Füge einige Variablen hinzu, um zu ändern, 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 ist eine Heatmap, die zeigt, wie sich die Lieferungen an allen Abholstellen 2016 im Umkreis des Empire State Buildings verändert haben. Große Konzentrationen (die roten Blobs) der Reiseziele in Midtown, vor allem rund um den Times Square, und entlang der 5th Avenue zwischen der 23. St. und der 14. St.

Screenshot 2017-05-09 um 10.40.01 AM.png

Basiskarte anpassen

Wenn Sie mit der Maps JavaScript API eine Google Maps-Karte erstellen, können Sie den Kartenstil mit einem JSON-Objekt festlegen. Für die Datenvisualisierung kann es hilfreich sein, die Farben der Karte stummzuschalten. Mit dem Google Maps API Styling Wizard können Sie unter mapstyle.withgoogle.com Kartenstile erstellen und ausprobieren.

Sie können einen Kartenstil beim Initialisieren eines Kartenobjekts oder zu einem späteren Zeitpunkt festlegen. So fügen Sie in der Funktion initMap() einen benutzerdefinierten Stil 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
();
}

Der folgende Stilstil 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"
     
}
   
]
 
}
]

Dem Nutzer Feedback geben

Auch wenn BigQuery normalerweise innerhalb von Sekunden antwortet

Füge deiner Webseite eine Benutzeroberfläche hinzu, die die Antwort der checkJobStatus()-Funktion zeigt, und eine animierte Grafik, um darauf hinzuweisen, dass die Abfrage ausgeführt wird.

Sie können die Abfragedauer, die zurückgegebenen Daten und die verarbeiteten Daten angeben.

Füge nach der Karte <div> einen HTML-Code hinzu, um der Seite einen Bereich zu erstellen, in dem du die Anzahl der von einer Abfrage zurückgegebenen Zeilen, den Zeitpunkt der Abfrage und die verarbeitete Datenmenge siehst.

<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 den Bereich oben links auf der Seite unterhalb der Kartentyp-Schaltflächen und der Zeichensymbolleiste wie im Snippet unten zu positionieren.

#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 bei Bedarf ausgeblendet werden. Außerdem wird JavaScript- und CSS-Code angezeigt, mit dem sie angezeigt wird, wenn ein BigQuery-Job ausgeführt wird.

Fügen Sie HTML-Code hinzu, um eine animierte Grafik anzuzeigen. Im Code-Repository gibt es eine Image-Datei mit dem Namen loader.gif im Ordner img.

<img id="spinner" src="img/loader.gif">

Fügen Sie 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 zuletzt JavaScript hinzu, um den Statusbereich zu aktualisieren und die Grafik während der Ausführung einer Abfrage ein- oder auszublenden. Je nachdem, welche Informationen verfügbar sind, können Sie mit dem Objekt response das Steuerfeld aktualisieren.

Beim Prüfen eines aktuellen Jobs können Sie die Property response.statistics verwenden. Wenn der Job abgeschlossen ist, kannst du auf die Properties response.totalRows und response.totalBytesProcessed zugreifen. Es ist sinnvoll, wie im Codebeispiel unten für den Nutzer Millisekunden in Sekunden und Bytes in Anzeige umzuwandeln.

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);
 
})
}

Sie können die Animation umschalten, indem Sie für die Sichtbarkeit eine Funktion einfügen. Mit dieser Funktion wird die Deckkraft aller HTML-DOM-Elemente ein- oder ausgeblendet.

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 schließlich diese Methode auf, bevor Sie eine Abfrage verarbeiten und nachdem das Abfrageergebnis von BigQuery zurückgegeben wurde.

Der Code ruft die Funktion fadeToggle auf, wenn der Nutzer das Zeichnen eines Rechtecks beendet hat.

drawingManager.addListener('rectanglecomplete', rectangle => {
 
//show an animation to indicate that something is happening.
  fadeToggle
(document.getElementById('spinner'));
  rectangleQuery
(rectangle.getBounds());
});

Wenn die Abfrageantwort eingegangen ist, rufe fadeToggle() 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:

Screenshot 2017-05-10 um 14:32:19 Uhr.png

Sehen Sie sich das vollständige Beispiel in step8/map.html an.

14. Zu berücksichtigende Punkte

Zu viele Markierungen

Wenn Sie mit sehr großen Tabellen arbeiten, gibt Ihre Abfrage möglicherweise zu viele Zeilen zurück, um sie effizient auf einer Karte anzuzeigen. Beschränken Sie die Ergebnisse, indem Sie eine WHERE-Klausel oder eine LIMIT-Anweisung hinzufügen.

Das Zeichnen vieler Markierungen kann die Karte unlesbar machen. Erwäge die Verwendung der HeatmapLayer, um die Dichte anzuzeigen, oder Cluster-Markierungen, um anzugeben, wo viele Datenpunkte über ein einzelnes Symbol pro Cluster liegen. Weitere Informationen finden Sie in unserer Anleitung zum Markierungs-Clustering.

Abfragen optimieren

BigQuery scannt die gesamte Tabelle mit jeder Abfrage. Wählen Sie zum Optimieren der BigQuery-Kontingentnutzung nur die Spalten aus, die Sie in Ihrer Abfrage benötigen.

Abfragen werden schneller ausgeführt, wenn Sie Längen- und Breitengrade als Gleitkommazahlen und nicht als Strings speichern.

Interessante Ergebnisse exportieren

In den folgenden Beispielen muss der Endnutzer anhand der BigQuery-Tabelle authentifiziert werden, die nicht für jeden Anwendungsfall geeignet ist. Wenn Sie interessante Muster entdeckt haben, können Sie sie einfacher an eine breitere Zielgruppe weitergeben. Exportieren Sie dazu die Ergebnisse aus BigQuery und erstellen Sie mithilfe der Google Maps-Datenschicht ein statisches Dataset.

Die Google Maps Platform-Nutzungsbedingungen müssen erfüllt sein. Weitere Informationen zu den Preisen für die Google Maps Platform finden Sie in der Onlinedokumentation.

Jetzt Daten auswerten!

Es gibt einige öffentliche Datasets in BigQuery mit Spalten für Breiten- und Längengrad, z. B. die NYC Taxi-Datasets von 2009–2016, Uber- und Lyft NYC-Reisedaten und das GDELT-Dataset.

15. Glückwunsch!

Wir hoffen, dass es Ihnen gelingt, mit einigen geografischen Abfragen nach BigQuery-Tabellen schnell loszulegen und so Muster zu erkennen und sie auf einer Google Maps-Karte darzustellen. Viel Spaß beim Kartografieren!

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 zu BigQuery

Sehen Sie sich die Anleitung zum Erstellen einer einfachen Anwendung mit der BigQuery API an.

Weitere Informationen zum Aktivieren von Nutzerinteraktionen zum Zeichnen von Formen auf Google Maps finden Sie im Entwicklerleitfaden für die Zeichenbibliothek.

Sehen Sie sich die weiteren Möglichkeiten an, wie Sie Daten auf einer Google Maps-Karte visualisieren können.

Im Leitfaden Erste Schritte für den JavaScript Client AP erfahren Sie mehr über die grundlegenden Konzepte für den Zugriff auf andere Google APIs mit der Client API.