1. Przegląd
Mapy mogą być bardzo przydatnym narzędziem do wizualizacji wzorców w zbiorze danych, które są w jakiś sposób powiązane z lokalizacją. Może to być nazwa miejsca, konkretna wartość szerokości i długości geograficznej lub nazwa obszaru o określonych granicach, np. okręgu spisowego lub kodu pocztowego.
Gdy te zbiory danych stają się bardzo duże, wysyłanie do nich zapytań i wizualizowanie ich za pomocą konwencjonalnych narzędzi może być trudne. Korzystając z Google BigQuery do wykonywania zapytań dotyczących danych oraz z interfejsów Google Maps API do tworzenia zapytań i wizualizacji wyników, możesz szybko badać geograficzne wzorce w swoich danych przy minimalnej konfiguracji i kodowaniu oraz bez konieczności zarządzania systemem do przechowywania bardzo dużych zbiorów danych.
Co utworzysz
W tym module nauczysz się pisać i uruchamiać zapytania, które pokazują, jak dostarczać oparte na lokalizacji statystyki dotyczące bardzo dużych publicznych zbiorów danych przy użyciu BigQuery. Utworzysz też stronę internetową, która wczytuje mapę za pomocą interfejsu Google Maps Platform JavaScript API, a następnie uruchamia i wizualizuje zapytania przestrzenne dotyczące tych samych bardzo dużych publicznych zbiorów danych za pomocą biblioteki klienta interfejsów API Google dla JavaScriptu i interfejsu BigQuery API.
Czego się nauczysz
- Jak w kilka sekund wysyłać zapytania do zbiorów danych o lokalizacji o rozmiarze petabajtów za pomocą BigQuery, używając zapytań SQL, funkcji zdefiniowanych przez użytkownika i interfejsu BigQuery API
- Jak używać Google Maps Platform, aby dodać mapę Google do strony internetowej i umożliwić użytkownikom rysowanie na niej kształtów
- Jak wizualizować zapytania dotyczące dużych zbiorów danych na mapie Google, tak jak na przykładowym obrazie poniżej, który pokazuje gęstość lokalizacji taksówek w 2016 roku w przypadku przejazdów rozpoczynających się w bloku wokół Empire State Building.
Czego potrzebujesz
- Podstawowa znajomość języków HTML, CSS, JavaScript, SQL i Narzędzi deweloperskich w Chrome
- nowoczesną przeglądarkę, np. Chrome, Firefox, Safari lub Edge w najnowszej wersji;
- wybrany edytor tekstu lub IDE;
Technologia
BigQuery
BigQuery to usługa Google do analizy danych w przypadku bardzo dużych zbiorów danych. Ma interfejs API RESTful i obsługuje zapytania napisane w SQL. Jeśli masz dane z wartościami szerokości i długości geograficznej, możesz ich używać do wysyłania zapytań o dane według lokalizacji. Zaletą jest możliwość wizualnego eksplorowania bardzo dużych zbiorów danych w celu wyszukiwania wzorców bez konieczności zarządzania infrastrukturą serwera lub bazy danych. Dzięki ogromnej skalowalności i zarządzanej infrastrukturze BigQuery możesz uzyskać odpowiedzi na pytania w ciągu kilku sekund, niezależnie od tego, jak duże są Twoje tabele.
Google Maps Platform
Google Maps Platform zapewnia programowy dostęp do danych map, miejsc i tras Google. Obecnie korzysta z niej ponad 2 miliony witryn i aplikacji, aby udostępniać użytkownikom osadzone mapy i zapytania oparte na lokalizacji.
Warstwa rysowania interfejsu API JavaScript Map Google umożliwia rysowanie kształtów na mapie. Można je przekształcić w dane wejściowe do uruchamiania zapytań dotyczących tabel BigQuery, w których kolumnach są przechowywane wartości szerokości i długości geograficznej.
Aby rozpocząć, potrzebujesz projektu Google Cloud Platform z włączonymi interfejsami BigQuery i Maps API.
2. Pierwsze kroki
Konto Google
Jeśli nie masz jeszcze konta Google (Gmail lub Google Apps), musisz je utworzyć.
Utwórz projekt
Zaloguj się w konsoli Google Cloud Platform ( console.cloud.google.com) i utwórz nowy projekt. U góry ekranu znajduje się menu Projekt:
Po kliknięciu tego menu rozwijanego projektu pojawi się element menu, który umożliwia utworzenie nowego projektu:
W polu „Wpisz nową nazwę projektu” wpisz nazwę nowego projektu, np. „BigQuery Codelab”:
Wygenerujemy dla Ciebie identyfikator projektu. Identyfikator projektu to unikalna nazwa w ramach wszystkich projektów Google Cloud. Zapamiętaj identyfikator projektu, ponieważ będzie Ci później potrzebny. Podana powyżej nazwa jest już zajęta i nie będzie działać w Twoim przypadku. Wstaw swój identyfikator projektu w miejsce, w którym w tych ćwiczeniach z programowania widzisz YOUR_PROJECT_ID.
Włącz płatności
Aby zarejestrować się w BigQuery, użyj projektu wybranego lub utworzonego w poprzednim kroku. W tym projekcie musi być włączone rozliczanie. Gdy płatności zostaną włączone, możesz włączyć BigQuery API.
Sposób włączania płatności zależy od tego, czy tworzysz nowy projekt, czy ponownie włączasz płatności w przypadku istniejącego projektu.
Google oferuje 12-miesięczną bezpłatną wersję próbną Google Cloud Platform o wartości do 300 USD, z której możesz skorzystać w tym laboratorium. Więcej informacji znajdziesz na stronie https://cloud.google.com/free/.
Nowe projekty
Gdy tworzysz nowy projekt, wyświetla się prośba o wybranie konta rozliczeniowego, które chcesz z nim połączyć. Jeśli masz tylko 1 konto rozliczeniowe, zostanie ono automatycznie połączone z Twoim projektem.
Jeśli nie masz konta rozliczeniowego, musisz je utworzyć i włączyć płatności za projekt, zanim będziesz mieć możliwość korzystania z wielu funkcji Google Cloud Platform. Aby utworzyć nowe konto rozliczeniowe i włączyć płatności w projekcie, postępuj zgodnie z instrukcjami w artykule Tworzenie nowego konta rozliczeniowego.
Istniejące projekty
Jeśli masz projekt, w którym płatności zostały tymczasowo wyłączone, możesz je ponownie włączyć:
- Otwórz konsolę Cloud Platform.
- Na liście projektów wybierz projekt, dla którego chcesz ponownie włączyć płatności.
- Otwórz menu po lewej stronie konsoli i kliknij Płatności
. Pojawi się prośba o wybranie konta rozliczeniowego.
- Kliknij Ustaw konto.
Tworzenie nowego konta rozliczeniowego
Aby utworzyć nowe konto rozliczeniowe:
- Otwórz konsolę Cloud Platform i zaloguj się. Jeśli nie masz jeszcze konta, zarejestruj się.
- Otwórz menu po lewej stronie konsoli i kliknij Płatności
.
- Kliknij przycisk Nowe konto rozliczeniowe. (Pamiętaj, że jeśli to nie jest Twoje pierwsze konto rozliczeniowe, musisz najpierw otworzyć listę kont rozliczeniowych. W tym celu kliknij nazwę obecnego konta rozliczeniowego u góry strony, a potem kliknij Zarządzaj kontami rozliczeniowymi).
- Wpisz nazwę konta rozliczeniowego i informacje rozliczeniowe. Dostępne opcje zależą od kraju podanego w adresie rozliczeniowym. Pamiętaj, że w przypadku kont w Stanach Zjednoczonych nie możesz zmienić statusu podatkowego po utworzeniu konta.
- Kliknij Prześlij i włącz płatności.
Domyślnie osoba, która utworzy konto rozliczeniowe, jest administratorem rozliczeń tego konta.
Informacje o weryfikowaniu kont bankowych i dodawaniu zastępczych form płatności znajdziesz w artykule Dodawanie, usuwanie i aktualizowanie formy płatności.
Włączanie interfejsu BigQuery API
Aby włączyć interfejs BigQuery API w projekcie, otwórz stronę BigQuery API w Marketplace w konsoli i kliknij niebieski przycisk „Włącz”.
3. Wykonywanie zapytań o dane o lokalizacji w BigQuery
Dane o lokalizacji przechowywane w BigQuery w postaci wartości szerokości i długości geograficznej możesz wysyłać na 3 sposoby.
- Zapytania dotyczące prostokątów: określ obszar zainteresowania jako zapytanie, które wybiera wszystkie wiersze w zakresie od minimalnej do maksymalnej szerokości i długości geograficznej.
- Zapytania o promień: określ obszar zainteresowania, obliczając okrąg wokół punktu za pomocą wzoru Haversine i funkcji matematycznych, aby modelować kształt Ziemi.
- Zapytania dotyczące wielokątów: określ niestandardowy kształt i użyj funkcji zdefiniowanej przez użytkownika, aby wyrazić logikę punktu w wielokącie potrzebną do sprawdzenia, czy szerokość i długość geograficzna każdego wiersza mieszczą się w tym kształcie.
Aby rozpocząć, użyj edytora zapytań w sekcji BigQuery w konsoli Google Cloud Platform, aby uruchomić te zapytania na danych taksówek w Nowym Jorku.
Standardowa wersja SQL a starsza wersja SQL
BigQuery obsługuje 2 wersje SQL: starszą wersję SQL i standardową wersję SQL. Ta druga to norma ANSI z 2011 r. Na potrzeby tego samouczka użyjemy standardowej wersji SQL, ponieważ jest ona bardziej zgodna ze standardami.
Jeśli chcesz uruchomić starszą wersję SQL w edytorze BigQuery, wykonaj te czynności:
- Kliknij przycisk „Więcej”.
- W menu wybierz „Ustawienia zapytania”.
- W sekcji „Dialekt SQL” kliknij opcję „Starszy”.
- Kliknij przycisk „Zapisz”.
Zapytania dotyczące prostokątów
Zapytania o prostokąt są dość proste do utworzenia w BigQuery. Wystarczy dodać klauzulę WHERE
, która ogranicza zwracane wyniki do tych, których lokalizacje mieszczą się w przedziale wartości minimalnej i maksymalnej szerokości i długości geograficznej.
Wypróbuj poniższy przykład w konsoli BigQuery. To zapytanie zwraca średnie statystyki przejazdów, które rozpoczęły się na obszarze w kształcie prostokąta obejmującym Midtown i Dolny Manhattan. Możesz wypróbować 2 różne lokalizacje. Usuń komentarz z drugiego klauzuli WHERE
, aby uruchomić zapytanie dotyczące przejazdów, które rozpoczęły się na lotnisku JFK.
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
Wyniki obu zapytań pokazują, że średnia odległość przejazdu, opłata i napiwek w przypadku odbioru w tych 2 lokalizacjach znacznie się różnią.
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 |
Zapytania o promień
Zapytania o określonym promieniu można też łatwo tworzyć w SQL, jeśli znasz trochę matematyki. Za pomocą funkcji matematycznych starszej wersji SQL w BigQuery możesz utworzyć zapytanie SQL, które wykorzystuje wzór Haversine do przybliżonego obliczania okrągłego obszaru lub sferycznego wycinka na powierzchni Ziemi.
Oto przykładowa instrukcja SQL w BigQuery dla zapytania o okrąg wyśrodkowany w punkcie 40.73943, -73.99585
o promieniu 0,1 km.
Do przybliżonego określenia odległości odpowiadającej 1 stopniowi używa stałej wartości 111,045 km.
Poniższy przykład pochodzi ze strony 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
Kod SQL dla wzoru Haversine wygląda na skomplikowany, ale wystarczy, że podasz współrzędne środka okręgu, promień oraz nazwy projektu, zbioru danych i tabeli w BigQuery.
Oto przykładowe zapytanie, które oblicza średnie statystyki przejazdów w przypadku odbiorów w promieniu 100 m od Empire State Building. Skopiuj i wklej to zapytanie w konsoli internetowej BigQuery, aby zobaczyć wyniki. Zmień szerokość i długość geograficzną, aby porównać je z innymi obszarami, np. z lokalizacją w Bronxie.
#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
Wyniki zapytania są poniżej. Widać, że występują duże różnice w średnim napiwku, opłacie, odległości przejazdu, proporcjonalnej wielkości napiwku w stosunku do opłaty oraz średniej opłacie za przejechany kilometr.
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 |
Bronx
avg_tip | avg_fare | avg_distance | avg_tip_pc | avg_fare_mile |
0,52 | 17,63 | 4,75 | 4,74 | 10.9 |
Zapytania dotyczące wielokątów
SQL nie obsługuje zapytań dotyczących dowolnych kształtów innych niż prostokąty i okręgi. BigQuery nie ma natywnego typu danych geometrycznych ani indeksu przestrzennego, więc aby uruchamiać zapytania z użyciem kształtów wielokątów, musisz zastosować inne podejście niż w przypadku prostych zapytań SQL. Jednym ze sposobów jest zdefiniowanie funkcji geometrii w JavaScript i wykonanie jej jako funkcji zdefiniowanej przez użytkownika (UDF) w BigQuery.
Wiele operacji na geometriach można zapisać w JavaScript, więc łatwo jest wziąć jedną z nich i wykonać ją na tabeli BigQuery zawierającej wartości szerokości i długości geograficznej. Musisz przekazać niestandardowy wielokąt za pomocą funkcji UDF i przeprowadzić test na każdym wierszu, zwracając tylko te wiersze, w których szerokość i długość geograficzna znajdują się wewnątrz wielokąta. Więcej informacji o funkcjach zdefiniowanych przez użytkownika znajdziesz w dokumentacji BigQuery
Algorytm Point In Polygon
W JavaScript jest wiele sposobów na sprawdzenie, czy punkt znajduje się wewnątrz wielokąta. Oto przykład kodu, który jest przeniesioną z języka C znaną implementacją wykorzystującą algorytm śledzenia promieni do określania, czy punkt znajduje się wewnątrz wielokąta, czy na zewnątrz niego. W tym celu zlicza, ile razy nieskończenie długa linia przecina granicę kształtu. Wystarczy kilka wierszy kodu:
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;
}
Przenoszenie do JavaScriptu
Wersja tego algorytmu w JavaScript wygląda tak:
/* 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;
}
W przypadku standardowej wersji SQL w BigQuery podejście z funkcją UDF wymaga tylko jednej instrukcji, ale funkcja UDF musi być zdefiniowana w instrukcji jako funkcja tymczasowa. Oto przykład. Wklej poniższe polecenie SQL do okna edytora zapytań.
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
Gratulacje!
W BigQuery wykonaliśmy już 3 rodzaje zapytań przestrzennych. Jak widzisz, lokalizacja ma duży wpływ na dane wynikowe zapytań dotyczących tego zbioru danych, ale jeśli nie zgadniesz, gdzie uruchomić zapytania, trudno będzie Ci odkryć wzorce przestrzenne ad hoc za pomocą samych zapytań SQL.
Gdybyśmy tylko mogli wizualizować dane na mapie i przeglądać je, definiując dowolne obszary zainteresowań. Dzięki interfejsom API Map Google możesz to zrobić. Najpierw musisz włączyć interfejs Maps API, skonfigurować prostą stronę internetową działającą na Twoim komputerze i zacząć używać interfejsu BigQuery API do wysyłania zapytań ze strony internetowej.
4. Praca z interfejsami API Map Google
Po uruchomieniu prostych zapytań przestrzennych kolejnym krokiem jest wizualizacja danych wyjściowych, aby zobaczyć wzorce. Aby to zrobić, włączysz interfejs Maps API, utworzysz stronę internetową, która wysyła zapytania z mapy do BigQuery, a następnie rysuje wyniki na mapie.
Włączanie interfejsu Maps JavaScript API
Aby wykonać to ćwiczenie z programowania, musisz włączyć w projekcie interfejs API JavaScript Map Google z Google Maps Platform. W tym celu wykonaj następujące czynności:
- W konsoli Google Cloud Platform otwórz Marketplace.
- W Marketplace wyszukaj „Maps JavaScript API”.
- W wynikach wyszukiwania kliknij kartę interfejsu Maps JavaScript API.
- Kliknij przycisk „Włącz”.
Generowanie klucza interfejsu API
Aby wysyłać żądania do Google Maps Platform, musisz wygenerować klucz interfejsu API i przesyłać go wraz ze wszystkimi żądaniami. Aby wygenerować klucz interfejsu API:
- W konsoli Google Cloud Platform kliknij menu z 3 kreskami, aby otworzyć panel nawigacyjny po lewej stronie.
- Wybierz „Interfejsy API i usługi” > „Dane logowania”.
- Kliknij przycisk „Utwórz dane logowania”, a potem wybierz „Klucz interfejsu API”.
- Kopiowanie nowego klucza interfejsu API
Pobieranie kodu i konfigurowanie serwera WWW
Aby pobrać cały kod do tego laboratorium, kliknij ten przycisk:
Rozpakuj pobrany plik ZIP. Spowoduje to rozpakowanie folderu głównego (bigquery
), który zawiera po 1 folderze dla każdego kroku tego modułu oraz wszystkie potrzebne zasoby.
Foldery stepN
zawierają oczekiwany stan końcowy każdego kroku tego modułu. Są one podane w celach informacyjnych. Całą pracę związaną z kodowaniem będziemy wykonywać w katalogu o nazwie work
.
Konfigurowanie lokalnego serwera WWW
Możesz używać własnego serwera internetowego, ale ten przewodnik został zaprojektowany tak, aby dobrze współpracował z serwerem internetowym Chrome. Jeśli nie masz jeszcze tej aplikacji, możesz ją zainstalować z Chrome Web Store.
Po zainstalowaniu otwórz aplikację. W Chrome możesz to zrobić w ten sposób:
- Otwórz Chrome
- Na pasku adresu u góry wpisz chrome://apps.
- Naciśnij Enter
- W otwartym oknie kliknij ikonę serwera internetowego. Możesz też kliknąć aplikację prawym przyciskiem myszy, aby otworzyć ją w zwykłej lub przypiętej karcie, na pełnym ekranie lub w nowym oknie.
Następnie zobaczysz to okno dialogowe, które umożliwia skonfigurowanie lokalnego serwera internetowego:
- Kliknij „WYBIERZ FOLDER” i wskaż lokalizację, do której zostały pobrane przykładowe pliki z codelabu.
- W sekcji „Opcje” zaznacz pole „Automatycznie wyświetlaj plik index.html”:
- Przesuń przełącznik „Serwer WWW: URUCHOMIONY” w lewo, a potem z powrotem w prawo, aby zatrzymać i ponownie uruchomić serwer WWW.
5. Wczytywanie mapy i narzędzi do rysowania
Tworzenie podstawowej strony z mapą
Zacznij od prostej strony HTML, która wczytuje Mapę Google za pomocą interfejsu Maps JavaScript API i kilku wierszy kodu JavaScript. Kod z przykładowej prostej mapy w Google Maps Platform to świetne miejsce na rozpoczęcie pracy. Możesz go skopiować i wkleić do wybranego edytora tekstu lub IDE albo otworzyć plik index.html
w pobranych repozytoriach.
- Skopiuj
index.html
do folderuwork
w lokalnej kopii repozytorium. - Skopiuj folder img/ do folderu work/ w lokalnej kopii repozytorium.
- Otwórz projekt/
index.html
w edytorze tekstu lub IDE. - Zastąp
YOUR_API_KEY
utworzonym wcześniej kluczem interfejsu API.
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
async defer></script>
- W przeglądarce otwórz adres
localhost:<port>/work
, gdzieport
to numer portu określony w konfiguracji lokalnego serwera internetowego. Domyślny port to8887
. Powinny wyświetlić się pierwsze mapy.
Jeśli w przeglądarce pojawi się komunikat o błędzie, sprawdź, czy klucz API jest prawidłowy, a lokalny serwer WWW jest aktywny.
Zmienianie domyślnej lokalizacji i poziomu powiększenia
Kod, który ustawia lokalizację i poziom powiększenia, znajduje się w wierszach 27 i 28 pliku index.html. Obecnie jest wyśrodkowany na Sydney w Australii:
<script>
let map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
}
</script>
W tym samouczku używane są dane o przejazdach taksówkami w Nowym Jorku w BigQuery, więc w następnym kroku zmienisz kod inicjowania mapy, aby wyśrodkować lokalizację w Nowym Jorku na odpowiednim poziomie powiększenia – 13 lub 14.
Aby to zrobić, zaktualizuj powyższy blok kodu, aby wyśrodkować mapę na Empire State Building i dostosować poziom powiększenia do 14:
<script>
let map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.7484405, lng: -73.9878531},
zoom: 14
});
}
</script>
Następnie ponownie załaduj mapę w przeglądarce, aby zobaczyć wyniki.
Wczytaj biblioteki rysowania i wizualizacji
Aby dodać do mapy funkcje rysowania, zmień skrypt, który wczytuje interfejs Maps JavaScript API. Dodaj opcjonalny parametr, który informuje Google Maps Platform o włączeniu biblioteki rysowania.
W tym ćwiczeniu z programowania używamy też biblioteki HeatmapLayer
, więc zaktualizujesz skrypt, aby wysyłać żądania do biblioteki wizualizacji. Aby to zrobić, dodaj parametr libraries
i określ biblioteki visualization
i drawing
jako wartości rozdzielone przecinkami, np. libraries=
visualization,drawing
Powinien on wyglądać podobnie do tego:
<script src='http://maps.googleapis.com/maps/api/js?libraries=visualization,drawing&callback=initMap&key=YOUR_API_KEY' async defer></script>
Dodawanie DrawingManager
Aby używać kształtów narysowanych przez użytkownika jako danych wejściowych do zapytania, dodaj do mapy element DrawingManager
z włączonymi narzędziami Circle
, Rectangle
i Polygon
.
Warto umieścić cały DrawingManager
kod konfiguracji w nowej funkcji. W tym celu w kopii pliku index.html wykonaj te czynności:
- Dodaj funkcję o nazwie
setUpDrawingTools()
z tym kodem, aby utworzyć elementDrawingManager
i ustawić jego właściwośćmap
tak, aby odwoływała się do obiektu mapy na stronie.
Opcje przekazywane do google.maps.drawing.DrawingManager(options)
określają domyślny typ rysowania kształtu i opcje wyświetlania narysowanych kształtów. W przypadku wybierania obszarów mapy do wysyłania jako zapytań kształty powinny mieć zerową nieprzezroczystość. Więcej informacji o dostępnych opcjach znajdziesz w sekcji Opcje DrawingManager.
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);
}
- Wywołaj funkcję
setUpDrawingTools()
w funkcjiinitMap()
po utworzeniu obiektu mapy.
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.744593, lng: -73.990370}, // Manhattan, New York.
zoom: 12
});
setUpDrawingTools();
}
- Załaduj ponownie plik index.html i sprawdź, czy narzędzia do rysowania są widoczne. Sprawdź też, czy możesz ich używać do rysowania okręgów, prostokątów i wielokątów.
Aby narysować okrąg lub prostokąt, kliknij i przeciągnij. Wielokąty rysuje się, klikając każdy wierzchołek i klikając dwukrotnie, aby zakończyć rysowanie kształtu.
Obsługa zdarzeń rysowania
Potrzebujesz kodu do obsługi zdarzeń wywoływanych, gdy użytkownik skończy rysować kształt, tak samo jak potrzebujesz współrzędnych narysowanych kształtów do tworzenia zapytań SQL.
Kod do tego dodamy w późniejszym kroku, ale na razie utworzymy 3 puste moduły obsługi zdarzeń, które będą obsługiwać zdarzenia rectanglecomplete
, circlecomplete
i polygoncomplete
. Na tym etapie moduły obsługi nie muszą wykonywać żadnego kodu.
Dodaj na końcu funkcji setUpDrawingTools()
te informacje:
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.
});
Działający przykład tego kodu znajdziesz w lokalnej kopii repozytorium w folderze step2
: step2/map.html.
6. Korzystanie z interfejsu BigQuery Client API
Interfejs Google BigQuery Client API pomoże Ci uniknąć pisania dużej ilości kodu szablonowego potrzebnego do tworzenia żądań, analizowania odpowiedzi i obsługi uwierzytelniania. W tym module używamy interfejsu BigQuery API za pomocą biblioteki klienta interfejsów API Google w JavaScript, ponieważ będziemy tworzyć aplikację przeglądarkową.
Następnie dodasz kod, który wczyta ten interfejs API na stronie internetowej i umożliwi korzystanie z niego do interakcji z BigQuery.
Dodawanie interfejsu Google Client API w JavaScript
Do wykonywania zapytań w BigQuery będziesz używać interfejsu Google Client API w JavaScript. W kopii pliku index.html
(w folderze work
) załaduj interfejs API za pomocą tagu <script>
w ten sposób: Umieść tag bezpośrednio pod tagiem <script>
, który wczytuje interfejs API Map Google:
<script src='https://apis.google.com/js/client.js'></script>
Po wczytaniu interfejsu Google Client API autoryzuj użytkownika, aby uzyskać dostęp do danych w BigQuery. Możesz to zrobić za pomocą OAuth 2.0. Najpierw musisz skonfigurować dane logowania w projekcie w konsoli Google Cloud.
Tworzenie danych logowania OAuth 2.0
- W konsoli Google Cloud w Menu nawigacyjnym wybierz Interfejsy API i usługi > Dane logowania.
Zanim skonfigurujesz dane logowania, musisz dodać konfigurację ekranu autoryzacji, który zobaczy użytkownik końcowy Twojej aplikacji, gdy będzie autoryzować dostęp aplikacji do danych BigQuery w jego imieniu.
Aby to zrobić, kliknij kartę Ekran zgody OAuth. 2. Musisz dodać BigQuery API do zakresów tego tokena. W sekcji Zakresy interfejsów API Google kliknij przycisk Dodaj zakres. 3. Na liście zaznacz pole obok pozycji BigQuery API z zakresem ../auth/bigquery
. 4. Kliknij Dodaj. 5. Wpisz nazwę w polu „Nazwa aplikacji”. 6. Kliknij Zapisz, aby zapisać ustawienia. 7. Następnie utworzysz identyfikator klienta OAuth. Aby to zrobić, kliknij Utwórz dane logowania:
- W menu kliknij Identyfikator klienta OAuth.
- W sekcji Typ aplikacji wybierz Aplikacja internetowa.
- W polu Nazwa aplikacji wpisz nazwę projektu. Na przykład „BigQuery i Mapy”.
- W sekcji Ograniczenia w polu Autoryzowane źródła JavaScript wpisz adres URL hosta lokalnego, w tym numery portów. Na przykład:
http://localhost:8887
- Kliknij przycisk Utwórz.
W wyskakującym okienku zobaczysz identyfikator i tajny klucz klienta. Identyfikator klienta jest potrzebny do uwierzytelniania w BigQuery. Skopiuj go i wklej w work/index.html
jako nową globalną zmienną JavaScript o nazwie clientId
.
let clientId = 'YOUR_CLIENT_ID';
7. Autoryzacja i inicjowanie
Zanim zainicjujesz mapę, musisz autoryzować użytkownika, aby miał dostęp do BigQuery. W tym przykładzie używamy protokołu OAuth 2.0 zgodnie z opisem w sekcji autoryzacji w dokumentacji interfejsu API JavaScript po stronie klienta. Do wysyłania zapytań musisz używać identyfikatora klienta OAuth i identyfikatora projektu.
Gdy interfejs Google Client API zostanie wczytany na stronie internetowej, wykonaj te czynności:
- Autoryzuj użytkownika.
- Jeśli użytkownik jest autoryzowany, wczytaj interfejs BigQuery API.
- Załaduj i zainicjuj mapę.
Przykład gotowej strony HTML znajdziesz w step3/map.html.
Autoryzowanie użytkownika
Użytkownik końcowy aplikacji musi autoryzować aplikację, aby mogła ona uzyskać dostęp do danych w BigQuery w jego imieniu. Logiką OAuth zajmuje się interfejs Google Client API dla JavaScript.
W rzeczywistej aplikacji masz wiele możliwości integracji etapu autoryzacji.
Możesz na przykład wywołać funkcję authorize()
z elementu interfejsu, takiego jak przycisk, lub po wczytaniu strony. W tym przypadku autoryzujemy użytkownika po wczytaniu interfejsu Google Client API for JavaScript, używając funkcji wywołania zwrotnego w metodzie gapi.load()
.
Napisz kod bezpośrednio po tagu <script>
, który wczytuje interfejs Google Client API dla JavaScriptu, aby wczytać zarówno bibliotekę klienta, jak i moduł uwierzytelniania, dzięki czemu będziemy mogli od razu uwierzytelnić użytkownika.
<script src='https://apis.google.com/js/client.js'></script>
<script type='text/javascript'>
gapi.load('client:auth', authorize);
</script>
Po autoryzacji wczytaj interfejs BigQuery API.
Po autoryzacji użytkownika załaduj interfejs BigQuery API.
Najpierw wywołaj funkcję gapi.auth.authorize()
ze zmienną clientId
dodaną w poprzednim kroku. Obsłuż odpowiedź w funkcji wywołania zwrotnego o nazwie handleAuthResult
.
Parametr immediate
określa, czy użytkownikowi ma się wyświetlać wyskakujące okienko. Ustaw wartość true
, aby pominąć wyskakujące okienko autoryzacji, jeśli użytkownik jest już autoryzowany.
Dodaj do strony funkcję o nazwie handleAuthResult()
. Funkcja musi przyjmować parametr authresult
, który pozwoli Ci kontrolować przepływ logiki w zależności od tego, czy użytkownik został autoryzowany.
Dodaj też funkcję o nazwie loadApi
, która wczytuje interfejs BigQuery API, jeśli użytkownik zostanie pomyślnie autoryzowany.
Dodaj logikę w funkcji handleAuthResult()
, aby wywołać loadApi()
, jeśli do funkcji zostanie przekazany obiekt authResult
, a właściwość error
obiektu ma wartość false
.
Dodaj kod do funkcji loadApi()
, aby wczytać BigQuery API za pomocą metody gapi.client.load()
.
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');
}
Wczytywanie mapy
Ostatnim krokiem jest zainicjowanie mapy. Aby to zrobić, musisz nieco zmienić kolejność logiki. Obecnie jest on inicjowany po wczytaniu interfejsu JavaScript API Map Google.
Możesz to zrobić, wywołując funkcję initMap()
z metody then()
po metodzie load()
na obiekcie gapi.client
.
// Load BigQuery client API
function loadApi(){
gapi.client.load('bigquery', 'v2').then(
() => initMap()
);
}
8. Pojęcia związane z interfejsem BigQuery API
Wywołania BigQuery API zwykle są wykonywane w ciągu kilku sekund, ale nie zawsze od razu zwracają odpowiedź. Potrzebujesz logiki, która będzie odpytywać BigQuery o stan długotrwałych zadań i pobierać wyniki dopiero po zakończeniu zadania.
Pełny kod tego kroku znajdziesz w pliku step4/map.html.
Wysyłanie prośby
Dodaj do funkcji work/index.html
funkcję JavaScript, która będzie wysyłać zapytanie za pomocą interfejsu API, oraz zmienne do przechowywania wartości zbioru danych BigQuery i projektu zawierającego tabelę, do której chcesz wysłać zapytanie, a także identyfikator projektu, w odniesieniu do którego będą naliczane opłaty.
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.
});
}
Sprawdzanie stanu zadania
Funkcja checkJobStatus
poniżej pokazuje, jak okresowo sprawdzać stan zadania za pomocą metody interfejsu API get
i wartości jobId
zwróconej przez pierwotne żądanie zapytania. Oto przykład, który jest uruchamiany co 500 milisekund, dopóki zadanie nie zostanie ukończone.
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]);
});
}
Zmodyfikuj metodę sendQuery
, aby wywoływała metodę checkJobStatus()
jako wywołanie zwrotne w wywołaniu request.execute()
. Przekaż identyfikator zadania do checkJobStatus
. Jest to widoczne w obiekcie odpowiedzi jako jobReference.jobId
.
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));
}
Uzyskiwanie wyników zapytania
Aby uzyskać wyniki zapytania po jego zakończeniu, użyj wywołania interfejsu API jobs.getQueryResults
. Dodaj do strony funkcję o nazwie getQueryResults()
, która akceptuje parametr jobId
:
function getQueryResults(jobId){
let request = gapi.client.bigquery.jobs.getQueryResults({
'projectId': billingProjectId,
'jobId': jobId
});
request.execute(response => {
// Do something with the results.
})
}
9. Wykonywanie zapytań o dane o lokalizacji za pomocą interfejsu BigQuery API
Istnieją 3 sposoby używania SQL do uruchamiania zapytań przestrzennych na danych w BigQuery:
- wybierać za pomocą prostokąta (zwanego też ramką ograniczającą),
- wybrać według promienia,
- zaawansowanej funkcji funkcji zdefiniowanych przez użytkownika.
Przykłady zapytań dotyczących prostokątów ograniczających i promieni znajdziesz w sekcji Funkcje matematyczne w starszej wersji SQL w BigQuery w rozdziale „Zaawansowane przykłady”.
W przypadku zapytań dotyczących pola ograniczenia i promienia możesz wywołać metodę query
interfejsu BigQuery API. Skonstruuj zapytanie SQL dla każdego zapytania i przekaż je do funkcji sendQuery
utworzonej w poprzednim kroku.
Działający przykład kodu na tym etapie znajdziesz w pliku step4/map.html.
Zapytania dotyczące prostokątów
Najprostszym sposobem wyświetlania danych BigQuery na mapie jest wysłanie zapytania o wszystkie wiersze, w których szerokość i długość geograficzna mieszczą się w prostokącie, przy użyciu porównania „mniejsze niż” i „większe niż”. Może to być bieżący widok mapy lub kształt narysowany na mapie.
Aby użyć kształtu narysowanego przez użytkownika, zmień kod w index.html
, aby obsługiwać zdarzenie rysowania wywoływane po narysowaniu prostokąta. W tym przykładzie kod używa metody getBounds()
na obiekcie prostokąta, aby uzyskać obiekt reprezentujący zakres prostokąta we współrzędnych mapy, i przekazuje go do funkcji o nazwie rectangleQuery
:
drawingManager.addListener('rectanglecomplete', rectangle => rectangleQuery(rectangle.getBounds()));
Funkcja rectangleQuery
musi tylko używać współrzędnych prawego górnego (północno-wschodniego) i lewego dolnego (południowo-zachodniego) rogu, aby utworzyć porównanie mniejsze/większe z każdym wierszem w tabeli BigQuery. Oto przykład zapytania do tabeli, która ma kolumny o nazwach 'pickup_latitude'
i 'pickup_longitude'
przechowujące wartości lokalizacji.
Określanie tabeli BigQuery
Aby wysłać zapytanie do tabeli za pomocą interfejsu BigQuery API, musisz podać w zapytaniu SQL pełną nazwę tabeli. W standardowej wersji SQL format to project.dataset.tablename
. W starszej wersji SQL jest to project.dataset.tablename
.
Dostępnych jest wiele tabel z informacjami o przejazdach taksówkami w Nowym Jorku. Aby je wyświetlić, otwórz konsolę internetową BigQuery i rozwiń pozycję menu „Publiczne zbiory danych”. Znajdź zbiór danych o nazwie new_york
i rozwiń go, aby wyświetlić tabele. Wybierz tabelę przejazdów taksówkami Yellow Taxi: bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2016
).
Określanie identyfikatora projektu
W wywołaniu interfejsu API musisz podać nazwę projektu Google Cloud Platform na potrzeby rozliczeń. W tym laboratorium kodowania nie jest to ten sam projekt co projekt zawierający tabelę. Jeśli pracujesz z tabelą utworzoną we własnym projekcie przez przesłanie danych, ten identyfikator projektu będzie taki sam jak w instrukcji SQL.
Dodaj do kodu zmienne JavaScriptu, aby przechowywać odwołania do projektu Public Datasets, który zawiera tabelę, na której wykonujesz zapytanie, a także nazwę tabeli i zbioru danych. Potrzebujesz też osobnej zmiennej, która będzie odwoływać się do Twojego identyfikatora projektu rozliczeniowego.
Dodaj do kopii pliku index.html globalne zmienne JavaScript o nazwach billingProjectId, publicProjectId, datasetId
i tableName
.
Zainicjuj zmienne 'publicProjectId'
, 'datasetId'
i 'tableName'
, używając szczegółów z projektu Publiczne zbiory danych BigQuery. Zainicjuj billingProjectId
własnym identyfikatorem projektu (tym, który został utworzony w sekcji „Przygotowanie” w tym ćwiczeniu).
let billingProjectId = 'YOUR_PROJECT_ID';
let publicProjectId = 'bigquery-public-data';
let datasetId = 'new_york_taxi_trips';
let tableName = 'tlc_yellow_trips_2016';
Teraz dodaj do kodu 2 funkcje, aby wygenerować SQL i wysłać zapytanie do BigQuery za pomocą funkcji sendQuery
utworzonej w poprzednim kroku.
Pierwsza funkcja powinna mieć nazwę rectangleSQL()
i przyjmować 2 argumenty: parę obiektów google.Maps.LatLng
reprezentujących rogi prostokąta we współrzędnych mapy.
Druga funkcja powinna nazywać się rectangleQuery()
. Spowoduje to przekazanie tekstu zapytania do funkcji sendQuery
.
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;
}
W tym momencie masz wystarczająco dużo kodu, aby wysłać do BigQuery zapytanie dotyczące wszystkich wierszy zawartych w prostokącie narysowanym przez użytkownika. Zanim dodamy inne metody zapytań dotyczące okręgów i kształtów rysowanych odręcznie, zobaczmy, jak obsługiwać dane zwracane przez zapytanie.
10. Wizualizacja odpowiedzi
Tabele BigQuery mogą być bardzo duże – zawierać petabajty danych – i powiększać się o setki tysięcy wierszy na sekundę. Dlatego ważne jest, aby ograniczyć ilość zwracanych danych, tak aby można było je narysować na mapie. Wyświetlenie lokalizacji każdego wiersza w bardzo dużym zbiorze wyników (dziesiątki tysięcy wierszy lub więcej) spowoduje, że mapa będzie nieczytelna. Istnieje wiele technik agregowania lokalizacji zarówno w zapytaniu SQL, jak i na mapie. Możesz też ograniczyć wyniki zwracane przez zapytanie.
Pełny kod tego kroku znajdziesz w pliku step5/map.html.
Aby ilość danych przesyłanych na stronę internetową w ramach tych ćwiczeń z programowania była rozsądna, zmodyfikuj funkcję rectangleSQL()
, dodając instrukcję, która ogranicza odpowiedź do 10 000 wierszy. W przykładzie poniżej jest to określone w zmiennej globalnej o nazwie recordLimit
, dzięki czemu wszystkie funkcje zapytań mogą używać tej samej wartości.
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;
}
Aby wizualizować gęstość lokalizacji, możesz użyć mapy termicznej. Interfejs Maps JavaScript API ma w tym celu klasę HeatmapLayer. Warstwa HeatmapLayer przyjmuje tablicę współrzędnych szerokości i długości geograficznej, więc dość łatwo jest przekształcić wiersze zwrócone przez zapytanie w mapę termiczną.
W funkcji getQueryResults
przekaż tablicę response.result.rows
do nowej funkcji JavaScript o nazwie doHeatMap()
, która utworzy mapę cieplną.
Każdy wiersz będzie miał właściwość o nazwie f
, która jest tablicą kolumn. Każda kolumna będzie mieć właściwość v
zawierającą wartość.
Kod musi przechodzić przez kolumny w każdym wierszu i wyodrębniać wartości.
W zapytaniu SQL prosisz tylko o wartości szerokości i długości geograficznej miejsc odbioru taksówek, więc w odpowiedzi będą tylko 2 kolumny.
Nie zapomnij wywołać funkcji setMap()
w warstwie mapy cieplnej po przypisaniu do niej tablicy pozycji. Dzięki temu będzie ona widoczna na mapie.
Oto przykład:
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);
}
W tym momencie powinna być możliwa:
- Otwieranie strony i autoryzacja w BigQuery
- Narysuj prostokąt w dowolnym miejscu w Nowym Jorku
- Wyświetl wyniki zapytania w postaci mapy termicznej.
Oto przykład wyniku zapytania o prostokąt w odniesieniu do danych z 2016 r. dotyczących taksówek w Nowym Jorku, przedstawionego w formie mapy cieplnej. Poniżej przedstawiamy rozkład odbiorów w okolicy Empire State Building w sobotę w lipcu:
11. Wykonywanie zapytań według promienia wokół punktu
Zapytania o określony promień są bardzo podobne. Za pomocą funkcji matematycznych starszej wersji SQL w BigQuery możesz utworzyć zapytanie SQL z użyciem wzoru Haversine, który przybliża okrągły obszar na powierzchni Ziemi.
Stosując tę samą technikę w przypadku prostokątów, możesz obsługiwać zdarzenie OverlayComplete
, aby uzyskać środek i promień narysowanego przez użytkownika okręgu, i w ten sam sposób tworzyć zapytanie SQL.
Działający przykład kodu z tego kroku znajdziesz w repozytorium kodu w pliku step6/map.html.
drawingManager.addListener('circlecomplete', circle => circleQuery(circle));
W kopii pliku index.html dodaj 2 nowe puste funkcje: circleQuery()
i haversineSQL()
.
Następnie dodaj circlecomplete
, który przekazuje środek i promień do nowej funkcji o nazwie circleQuery().
.
Funkcja circleQuery()
wywoła funkcję haversineSQL()
, aby utworzyć zapytanie SQL, a następnie wyśle zapytanie, wywołując funkcję sendQuery()
, jak w poniższym przykładzie kodu.
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;
}
Wypróbuj
Dodaj powyższy kod i wypróbuj narzędzie „Okrąg”, aby wybrać obszar na mapie. Wynik powinien wyglądać mniej więcej tak:
12. Wykonywanie zapytań dotyczących dowolnych kształtów
Podsumowanie: SQL nie obsługuje zapytań dotyczących dowolnych kształtów innych niż prostokąty i okręgi. BigQuery nie ma natywnego typu danych geometrycznych, więc aby uruchamiać zapytania z użyciem kształtów wielokątów, musisz zastosować inne podejście niż w przypadku prostych zapytań SQL.
Jedną z bardzo przydatnych funkcji BigQuery, której można użyć w tym celu, są funkcje zdefiniowane przez użytkownika (UDF). Funkcje UDF wykonują kod JavaScript w zapytaniu SQL.
Działający kod na potrzeby tego kroku znajdziesz w pliku step7/map.html.
Funkcje zdefiniowane przez użytkownika w interfejsie BigQuery API
Podejście do funkcji zdefiniowanych przez użytkownika w interfejsie BigQuery API nieco różni się od tego w konsoli internetowej: musisz wywołać jobs.insert method
.
W przypadku zapytań w standardowej wersji SQL wysyłanych przez interfejs API do użycia funkcji zdefiniowanej przez użytkownika wystarczy jedno wyrażenie SQL. Wartość useLegacySql
musi być ustawiona na false
. Poniższy przykład w JavaScript pokazuje funkcję, która tworzy i wysyła obiekt żądania wstawienia nowego zadania, w tym przypadku zapytania z funkcją zdefiniowaną przez użytkownika.
Działający przykład tego podejścia znajdziesz w 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));
}
Zapytanie SQL jest skonstruowane w ten sposób:
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;
}
Dzieją się tu 2 rzeczy. Najpierw kod tworzy instrukcję CREATE TEMPORARY FUNCTION
, która zawiera kod JavaScript sprawdzający, czy dany punkt znajduje się w wielokącie. Współrzędne wielokąta są wstawiane za pomocą wywołania metody JSON.stringify(poly)
, która przekształca tablicę JavaScript zawierającą pary współrzędnych x,y w ciąg znaków. Obiekt wielokąta jest przekazywany jako argument do funkcji, która tworzy kod SQL.
Po drugie, kod tworzy główną instrukcję SQL SELECT
. W tym przykładzie funkcja zdefiniowana przez użytkownika jest wywoływana w wyrażeniu WHERE
.
Integracja z interfejsem Maps API
Aby użyć tej funkcji z biblioteką rysowania interfejsu API Map Google, musimy zapisać wielokąt narysowany przez użytkownika i przekazać go do części UDF zapytania SQL.
Najpierw musimy obsłużyć zdarzenie polygoncomplete
rysowania, aby uzyskać współrzędne kształtu jako tablicę par długości i szerokości geograficznej:
drawingManager.addListener('polygoncomplete', polygon => {
let path = polygon.getPaths().getAt(0);
let queryPolygon = path.map(element => {
return [element.lng(), element.lat()];
});
polygonQuery(queryPolygon);
});
Funkcja polygonQuery
może następnie utworzyć funkcje JavaScript UDF jako ciąg znaków, a także instrukcję SQL, która będzie wywoływać funkcję UDF.
Działający przykład znajdziesz w pliku step7/map.html.
Przykładowe dane wyjściowe
Oto przykładowy wynik zapytania dotyczącego odbiorów z danych o żółtych taksówkach w Nowym Jorku w 2016 roku w BigQuery przy użyciu wielokąta rysowanego odręcznie. Wybrane dane są przedstawione w postaci mapy cieplnej.
13. Dalsze działania
Oto kilka sugestii, jak rozszerzyć ten samouczek, aby przyjrzeć się innym aspektom danych. Działający przykład tych pomysłów znajdziesz w repozytorium kodu w pliku step8/map.html.
Mapowanie miejsc docelowych
Do tej pory zmapowaliśmy tylko miejsca odbioru. Jeśli poprosisz o kolumny dropoff_latitude
i dropoff_longitude
oraz zmodyfikujesz kod mapy cieplnej, aby zamiast nich wykreślać te kolumny, możesz zobaczyć miejsca docelowe przejazdów taksówką, które rozpoczęły się w określonej lokalizacji.
Sprawdźmy na przykład, gdzie taksówki zwykle wysadzają pasażerów, którzy zamawiają przejazd w pobliżu Empire State Building.
Zmień kod instrukcji SQL w polygonSql()
, aby oprócz lokalizacji odbioru zażądać tych kolumn.
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;
}
Funkcja doHeatMap
może wtedy używać wartości odbioru. Obiekt wyniku ma schemat, który można sprawdzić, aby znaleźć lokalizację tych kolumn w tablicy. W tym przypadku byłyby one w pozycjach indeksu 2 i 3. Aby kod był łatwiejszy w zarządzaniu, te indeksy można odczytywać ze zmiennej. Uwaga: maxIntensity
mapy termicznej jest ustawiony tak, aby maksymalnie wyświetlać gęstość 20 miejsc docelowych na piksel.
Dodaj zmienne, aby móc zmieniać kolumny używane w danych mapy cieplnej.
// 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);
}
Oto mapa termiczna przedstawiająca rozkład miejsc docelowych wszystkich przejazdów rozpoczynających się w bezpośrednim sąsiedztwie Empire State Building w 2016 roku. Widać duże skupiska (czerwone plamy) miejsc docelowych w centrum miasta, zwłaszcza wokół Times Square, a także wzdłuż Piątej Alei między 23 a 14 Ulicą. Inne miejsca o dużym zagęszczeniu, które nie są widoczne na tym poziomie powiększenia, to lotniska La Guardia i JFK, World Trade Center i Battery Park.
Nadawanie stylu mapie bazowej
Gdy tworzysz mapę Google za pomocą interfejsu Maps JavaScript API, możesz ustawić styl mapy za pomocą obiektu JSON. W przypadku wizualizacji danych przydatne może być wyciszenie kolorów na mapie. Style map możesz tworzyć i wypróbowywać za pomocą kreatora stylu interfejsu Google Maps API na stronie mapstyle.withgoogle.com.
Styl mapy możesz ustawić podczas inicjowania obiektu mapy lub w dowolnym późniejszym momencie. Oto jak dodać styl niestandardowy w funkcji initMap()
:
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();
}
Przykładowy styl poniżej przedstawia mapę w odcieniach szarości z etykietami ciekawych miejsc.
[
{
"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"
}
]
}
]
Przekazywanie użytkownikowi informacji zwrotnych
Mimo że BigQuery zwykle odpowiada w ciągu kilku sekund, czasami warto pokazać użytkownikowi, że podczas wykonywania zapytania coś się dzieje.
Dodaj do strony interfejs, który będzie wyświetlać odpowiedź funkcji checkJobStatus()
, oraz animowaną grafikę wskazującą, że zapytanie jest w trakcie przetwarzania.
Możesz wyświetlać informacje takie jak czas trwania zapytania, ilość zwróconych danych i ilość przetworzonych danych.
Dodaj kod HTML po mapie <div>
, aby utworzyć panel na stronie, który będzie wyświetlać liczbę wierszy zwróconych przez zapytanie, czas wykonania zapytania i ilość przetworzonych danych.
<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>
Wygląd i położenie tego panelu są kontrolowane przez CSS. Dodaj CSS, aby umieścić panel w lewym górnym rogu strony pod przyciskami typu mapy i paskiem narzędzi do rysowania, jak w poniższym fragmencie kodu.
#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;
}
Animowaną grafikę można dodać do strony, ale ukryć ją do czasu, gdy będzie potrzebna. Za pomocą kodu JavaScript i CSS można ją wyświetlać, gdy działa zadanie BigQuery.
Dodaj kod HTML, aby wyświetlić animowaną grafikę. W folderze img
w repozytorium kodu znajduje się plik obrazu o nazwie loader.gif
.
<img id="spinner" src="img/loader.gif">
Dodaj CSS, aby umieścić obraz i domyślnie go ukryć, dopóki nie będzie potrzebny.
#spinner {
position: absolute;
top: 50%;
left: 50%;
margin-left: -32px;
margin-top: -32px;
opacity: 0;
z-index: -1000;
}
Na koniec dodaj kod JavaScript, aby zaktualizować panel stanu i wyświetlić lub ukryć grafikę, gdy jest wykonywane zapytanie. Możesz użyć obiektu response
, aby zaktualizować panel w zależności od dostępnych informacji.
Podczas sprawdzania bieżącego zadania możesz użyć właściwości response.statistics
. Po zakończeniu zadania możesz uzyskać dostęp do właściwości response.totalRows
i response.totalBytesProcessed
. Warto przekonwertować milisekundy na sekundy, a bajty na gigabajty, aby wyświetlać je w sposób pokazany w przykładzie kodu poniżej.
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';
}
}
Wywołuj tę metodę, gdy pojawi się odpowiedź na wywołanie checkJobStatus()
i gdy zostaną pobrane wyniki zapytania. Na przykład:
// 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);
})
}
Aby przełączać animowaną grafikę, dodaj funkcję sterującą jej widocznością. Ta funkcja przełącza przezroczystość dowolnego elementu DOM HTML, który zostanie do niej przekazany.
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;
}
}
Na koniec wywołaj tę metodę przed przetworzeniem zapytania i po otrzymaniu wyniku zapytania z BigQuery.
Ten kod wywołuje funkcję fadeToggle
, gdy użytkownik skończy rysować prostokąt.
drawingManager.addListener('rectanglecomplete', rectangle => {
//show an animation to indicate that something is happening.
fadeToggle(document.getElementById('spinner'));
rectangleQuery(rectangle.getBounds());
});
Po otrzymaniu odpowiedzi na zapytanie ponownie wywołaj funkcję fadeToggle()
, aby ukryć animowaną grafikę.
// 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);
})
}
Strona powinna wyglądać mniej więcej tak.
Zapoznaj się z pełnym przykładem w step8/map.html.
14. Istotne kwestie
Zbyt wiele znaczników
Jeśli pracujesz z bardzo dużymi tabelami, zapytanie może zwrócić zbyt wiele wierszy, aby można je było efektywnie wyświetlić na mapie. Ogranicz wyniki, dodając klauzulę WHERE
lub instrukcję LIMIT
.
Rysowanie wielu znaczników może sprawić, że mapa będzie nieczytelna. Rozważ użycie HeatmapLayer
, aby pokazać gęstość, lub znaczników klastra, aby wskazać, gdzie znajduje się wiele punktów danych, za pomocą jednego symbolu na klaster. Więcej informacji znajdziesz w naszym samouczku dotyczącym klastrowania znaczników.
Optymalizacja zapytań
BigQuery będzie skanować całą tabelę przy każdym zapytaniu. Aby zoptymalizować wykorzystanie limitu BigQuery, w zapytaniu wybieraj tylko potrzebne kolumny.
Zapytania będą szybsze, jeśli szerokość i długość geograficzna będą przechowywane jako liczby zmiennoprzecinkowe, a nie ciągi znaków.
Eksportowanie interesujących wyników
Przykłady te wymagają uwierzytelnienia użytkownika w tabeli BigQuery, co nie będzie odpowiednie w każdym przypadku. Gdy odkryjesz ciekawe wzorce, możesz łatwiej udostępnić je szerszemu gronu odbiorców, eksportując wyniki z BigQuery i tworząc statyczny zbiór danych za pomocą warstwy danych Map Google.
Nudne kwestie prawne
Pamiętaj o Warunkach korzystania z usługi Google Maps Platform. Więcej informacji o cenach Google Maps Platform znajdziesz w dokumentacji online.
Graj z większą ilością danych.
W BigQuery jest wiele publicznych zbiorów danych, które zawierają kolumny szerokości i długości geograficznej, np. zbiory danych NYC Taxi z lat 2009–2016, dane o przejazdach Uberem i Lyftem w Nowym Jorku oraz zbiór danych GDELT.
15. Gratulacje!
Mamy nadzieję, że dzięki temu szybko zaczniesz korzystać z zapytań geograficznych dotyczących tabel BigQuery, aby odkrywać wzorce i wizualizować je na mapie Google. Miłego mapowania!
Co dalej?
Jeśli chcesz dowiedzieć się więcej o Google Maps Platform lub BigQuery, zapoznaj się z tymi sugestiami.
Więcej informacji o bezserwerowej usłudze hurtowni danych Google, która może obsługiwać petabajty danych, znajdziesz w artykule Czym jest BigQuery.
Zapoznaj się z instrukcją tworzenia prostej aplikacji za pomocą BigQuery API.
Więcej informacji o włączaniu interakcji użytkownika w celu rysowania kształtów na mapie Google znajdziesz w przewodniku dla programistów dotyczącym biblioteki rysowania.
Sprawdź inne sposoby wizualizacji danych w Mapach Google.
Zapoznaj się z przewodnikiem dla początkujących użytkowników interfejsu Javascript Client API, aby poznać podstawowe pojęcia związane z używaniem interfejsu Client API do uzyskiwania dostępu do innych interfejsów API Google.