Google Haritalar Platformu (JavaScript) ile BigQuery'de konum verilerini sorgulama ve görselleştirme

1. Genel Bakış

Haritalar, bir veri kümesindeki konumla ilgili kalıpları görselleştirirken çok güçlü bir araç olabilir. Bu ilişki bir yerin adı, belirli bir enlem ve boylam değeri veya bir nüfus sayım bölgesi ya da posta kodu gibi belirli bir sınıra sahip bir alanın adı olabilir.

Bu veri kümeleri çok büyüdüğünde, geleneksel araçlar kullanılarak sorgulanması ve görselleştirilmesi zor olabilir. Verilere sorgu göndermek için Google BigQuery'yi, sorguyu oluşturmak ve çıkışı görselleştirmek için Google Haritalar API'lerini kullanarak çok az kurulum veya kodlama ile ve çok büyük veri kümelerini depolamak için bir sistemi yönetmek zorunda kalmadan verilerinizdeki coğrafi kalıpları hızlıca keşfedebilirsiniz.

Ne oluşturacaksınız?

Bu codelab'de, BigQuery'yi kullanarak çok büyük herkese açık veri kümeleri hakkında konuma dayalı analizler sağlamanın nasıl yapılacağını gösteren bazı sorgular yazıp çalıştıracaksınız. Ayrıca, Google Maps Platform JavaScript API'yi kullanarak bir harita yükleyen bir web sayfası oluşturacak, ardından JavaScript için Google API'leri İstemci Kitaplığı ve BigQuery API'yi kullanarak aynı çok büyük herkese açık veri kümelerine karşı uzamsal sorgular çalıştırıp görselleştireceksiniz.

Neler öğreneceksiniz?

  • BigQuery, SQL sorguları, kullanıcı tanımlı işlevler ve BigQuery API'yi kullanarak petabayt ölçeğindeki konum veri kümelerini saniyeler içinde sorgulama
  • Bir web sayfasına Google Haritası eklemek ve kullanıcıların harita üzerinde şekil çizebilmesini sağlamak için Google Haritalar Platformu'nu kullanma
  • Aşağıdaki örnek resimde olduğu gibi, büyük veri kümelerine yönelik sorguları Google Harita'da görselleştirme. Bu örnekte, 2016'da Empire State Binası çevresindeki bloktan başlayan yolculuklardaki taksi bırakma yerlerinin yoğunluğu gösterilmektedir.

Screen Shot 2017-05-09 at 11.01.12 AM.png

İhtiyacınız olanlar

  • HTML, CSS, JavaScript, SQL ve Chrome Geliştirme Araçları hakkında temel bilgi
  • Chrome, Firefox, Safari veya Edge'in son sürümleri gibi modern bir web tarayıcısı
  • Seçtiğiniz bir metin düzenleyici veya IDE

Teknoloji

BigQuery

BigQuery, çok büyük veri kümeleri için Google'ın veri analizi hizmetidir. RESTful API'ye sahiptir ve SQL ile yazılmış sorguları destekler. Enlem ve boylam değerleri içeren verileriniz varsa bu veriler, konum bazında sorgu oluşturmak için kullanılabilir. Avantajı, herhangi bir sunucu veya veritabanı altyapısını yönetmek zorunda kalmadan kalıplara bakmak için çok büyük veri kümelerini görsel olarak keşfedebilmenizdir. BigQuery'nin muazzam ölçeklenebilirliği ve yönetilen altyapısı sayesinde tablolarınız ne kadar büyürse büyüsün sorularınıza birkaç saniye içinde yanıt alabilirsiniz.

Google Haritalar Platformu

Google Haritalar Platformu, Google'ın harita, yer ve rota verilerine programatik erişim sağlar. 2 milyondan fazla web sitesi ve uygulama, kullanıcılarına yerleştirilmiş haritalar ve konuma dayalı sorgular sunmak için bu hizmeti kullanıyor.

Google Maps Platform JavaScript API Çizim Katmanı, haritada şekil çizmenize olanak tanır. Bunlar, sütunlarda enlem ve boylam değerleri depolanan BigQuery tablolarında sorgu çalıştırmak için girişe dönüştürülebilir.

Başlamak için BigQuery ve Haritalar API'lerinin etkinleştirildiği bir Google Cloud Platform projesine ihtiyacınız vardır.

2. Başlarken

Google Hesabı

Henüz bir Google Hesabınız (Gmail veya Google Apps) yoksa oluşturmanız gerekir.

Proje oluştur

Google Cloud Platform Console'da ( console.cloud.google.com) oturum açın ve yeni bir proje oluşturun. Ekranınızın üst kısmında bir Proje açılır menüsü bulunur:

f2a353c3301dc649.png

Bu proje açılır menüsünü tıkladığınızda yeni bir proje oluşturmanıza olanak tanıyan bir menü öğesi gösterilir:

56a42dfa7ac27a35.png

"Projeniz için yeni bir ad girin" yazan kutuya yeni projeniz için bir ad girin (örneğin, "BigQuery Codelab"):

Codelab - create project (1).png

Sizin için bir proje kimliği oluşturulur. Proje kimliği, tüm Google Cloud projelerinde benzersiz bir addır. Daha sonra kullanacağınız için proje kimliğinizi unutmayın. Yukarıdaki ad zaten alınmış olduğundan sizin için çalışmaz. Bu codelab'de YOUR_PROJECT_ID gördüğünüz her yere kendi proje kimliğinizi ekleyin.

Faturalandırmayı Etkinleştir

BigQuery'ye kaydolmak için önceki adımda seçilen veya oluşturulan projeyi kullanın. Bu projede faturalandırma etkinleştirilmiş olmalıdır. Faturalandırma etkinleştirildikten sonra BigQuery API'yi etkinleştirebilirsiniz.

Faturalandırmayı nasıl etkinleştireceğiniz, yeni bir proje oluşturup oluşturmadığınıza veya mevcut bir proje için faturalandırmayı yeniden etkinleştirip etkinleştirmediğinize bağlıdır.

Google, 300 ABD doları değerine kadar Google Cloud Platform kullanımı için 12 aylık ücretsiz deneme sürümü sunar. Bu Codelab'de kullanabileceğiniz bu deneme sürümü hakkında daha fazla bilgiyi https://cloud.google.com/free/ adresinde bulabilirsiniz.

Yeni projeler

Yeni bir proje oluşturduğunuzda, faturalandırma hesaplarınızdan hangisini projeye bağlamak istediğinizi seçmeniz istenir. Yalnızca bir faturalandırma hesabınız varsa bu hesap projenize otomatik olarak bağlanır.

Faturalandırma hesabınız yoksa birçok Google Cloud Platform özelliğini kullanabilmek için bir faturalandırma hesabı oluşturmanız ve projeniz için faturalandırmayı etkinleştirmeniz gerekir. Yeni bir faturalandırma hesabı oluşturmak ve projeniz için faturalandırmayı etkinleştirmek üzere Yeni faturalandırma hesabı oluşturma başlıklı makaledeki talimatları uygulayın.

Mevcut projeler

Faturalandırmayı geçici olarak devre dışı bıraktığınız bir projeniz varsa faturalandırmayı yeniden etkinleştirebilirsiniz:

  1. Cloud Platform Console'a gidin.
  2. Proje listesinden, faturalandırmayı yeniden etkinleştirmek istediğiniz projeyi seçin.
  3. Konsolun sol kısmındaki menüyü açın ve Faturalandırma 'yı seçin Faturalandırma. Bir faturalandırma hesabı seçmeniz istenir.
  4. Hesap belirle'yi tıklayın.

Yeni bir faturalandırma hesabı oluşturma

Yeni faturalandırma hesabı oluşturmak için:

  1. Cloud Platform Console'a gidin ve oturum açın. Hesabınız yoksa kaydolun.
  2. Konsolun sol kısmındaki menüyü açın ve Faturalandırma 'yı seçin. Faturalandırma
  3. Yeni faturalandırma hesabı düğmesini tıklayın. (Bu ilk faturalandırma hesabınız değilse önce sayfanın üst kısmına yakın bir yerde mevcut faturalandırma hesabınızın adını, ardından Faturalandırma hesaplarını yönetin'i tıklayarak faturalandırma hesabı listesini açmanız gerektiğini unutmayın.)
  4. Fatura hesabının adını ve fatura bilgilerinizi girin. Gördüğünüz seçenekler, fatura adresinizin bulunduğu ülkeye göre değişir. ABD hesaplarında, hesap oluşturulduktan sonra vergi durumunu değiştiremeyeceğinizi unutmayın.
  5. Gönder ve faturalandırmayı etkinleştir'i tıklayın.

Varsayılan olarak, faturalandırma hesabını oluşturan kişi hesabın faturalandırma yöneticisidir.

Banka hesaplarını doğrulama ve yedek ödeme yöntemleri ekleme hakkında bilgi edinmek için Ödeme yöntemlerini ekleme, kaldırma veya güncelleme başlıklı makaleyi inceleyin.

BigQuery API'yi etkinleştirme

Projenizde BigQuery API'yi etkinleştirmek için konsoldaki BigQuery API sayfası Marketplace'e gidin ve mavi "Etkinleştir" düğmesini tıklayın.

3. BigQuery'de konum verilerini sorgulama

BigQuery'de enlem ve boylam değerleri olarak depolanan konum verilerini sorgulamanın üç yolu vardır.

  • Dikdörtgen sorgular: İlgi alanını, minimum ve maksimum enlem ve boylam aralığındaki tüm satırları seçen bir sorgu olarak belirtin.
  • Yarıçap sorguları: Haversine formülünü ve matematik işlevlerini kullanarak bir nokta etrafında daire hesaplayıp dünyanın şeklini modelleyerek ilgi alanını belirtin.
  • Poligon sorguları: Özel bir şekil belirtin ve her satırın enlemi ile boylamının şeklin içinde olup olmadığını test etmek için gereken nokta-poligon mantığını ifade etmek üzere kullanıcı tanımlı bir işlev kullanın.

Başlamak için Google Cloud Platform Console'un BigQuery bölümündeki Sorgu Düzenleyici'yi kullanarak NYC taksi verileriyle ilgili aşağıdaki sorguları çalıştırın.

Standart SQL ve Eski SQL

BigQuery iki SQL sürümünü destekler: eski SQL ve standart SQL. İkincisi 2011 ANSI standardıdır. Bu eğitimin amaçları doğrultusunda, daha iyi standart uyumluluğu nedeniyle Standart SQL'i kullanacağız.

BigQuery düzenleyicisinde eski SQL'i yürütmek istiyorsanız aşağıdakileri yaparak bunu yapabilirsiniz:

  1. "Diğer" düğmesini tıklayın.
  2. Açılır menüden "Sorgu ayarları"nı seçin.
  3. "SQL dili" bölümünde "Eski" radyo düğmesini seçin.
  4. "Kaydet" düğmesini tıklayın.

Dikdörtgen Sorgular

Dikdörtgen sorgular, BigQuery'de oldukça kolay bir şekilde oluşturulabilir. Yalnızca döndürülen sonuçları enlem ve boylam için minimum ve maksimum değerler arasında konumlara sahip olanlarla sınırlayan bir WHERE ifadesi eklemeniz gerekir.

BigQuery konsolunda aşağıdaki örneği deneyin. Bu sorgu, şehir merkezi ve Aşağı Manhattan'ı içeren dikdörtgen bir alanda başlayan yolculuklarla ilgili bazı ortalama gezi istatistiklerini sorgular. Deneyebileceğiniz iki farklı konum vardır. JFK Havaalanı'nda başlayan yolculuklarla ilgili sorguyu çalıştırmak için ikinci WHERE ifadesinin yorumunu kaldırın.

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

İki sorgunun sonuçları, iki konumdaki teslim alma işlemleri için ortalama yolculuk mesafesi, ücret ve bahşiş açısından büyük farklılıklar olduğunu gösteriyor.

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

Yarıçap Sorguları

Biraz matematik biliyorsanız yarıçap sorgularını SQL'de oluşturmak da kolaydır. BigQuery'nin eski SQL matematik işlevlerini kullanarak, yeryüzünde dairesel bir alanı veya küresel bir kapağı yaklaşık olarak hesaplayan Haversine Formülü'nü kullanan bir SQL sorgusu oluşturabilirsiniz.

İşte 40.73943, -73.99585 merkezli ve 0,1 km yarıçaplı bir daire sorgusu için örnek bir BigQuery SQL ifadesi.

Bir derecenin temsil ettiği mesafeyi yaklaşık olarak hesaplamak için 111,045 kilometrelik sabit bir değer kullanır.

Bu, http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ adresinde bulunan bir örneğe dayanmaktadır:

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 

Haversine Formülü'nün SQL'i karmaşık görünse de yapmanız gereken tek şey daire merkezinizin koordinatını, yarıçapı ve BigQuery için proje, veri kümesi ve tablo adlarını girmektir.

Aşağıda, Empire State Binası'nın 100 metre yakınındaki teslim alma noktaları için bazı ortalama seyahat istatistiklerini hesaplayan bir sorgu örneği verilmiştir. Sonuçları görmek için bunu kopyalayıp BigQuery web konsoluna yapıştırın. Bronx'taki konum gibi diğer alanlarla karşılaştırmak için enlem ve boylamı değiştirin.

#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

Sorgunun sonuçları aşağıda verilmiştir. Ortalama bahşiş, ücret, yolculuk mesafesi, bahşişin ücrete göre orantılı büyüklüğü ve sürüş başına ortalama ücret arasında büyük farklar olduğunu görebilirsiniz.

Empire State Binası:

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

Poligon Sorguları

SQL, dikdörtgen ve daire dışında rastgele şekiller kullanılarak sorgulama yapılmasını desteklemez. BigQuery'de yerel bir geometri veri türü veya uzamsal dizin yoktur. Bu nedenle, çokgen şekilleri kullanarak sorgu çalıştırmak için basit SQL sorgularından farklı bir yaklaşım kullanmanız gerekir. Bir yaklaşım, JavaScript'te bir geometri işlevi tanımlayıp bunu BigQuery'de kullanıcı tanımlı işlev (UDF) olarak yürütmektir.

Birçok geometri işlemi JavaScript'te yazılabilir. Bu nedenle, enlem ve boylam değerlerini içeren bir BigQuery tablosuna karşı kolayca bir işlem alıp yürütebilirsiniz. Özel poligonu bir UDF aracılığıyla iletmeniz ve her satıra karşı bir test gerçekleştirmeniz gerekir. Yalnızca enlem ve boylamın poligonun içinde olduğu satırları döndürün. BigQuery referansında UDF'ler hakkında daha fazla bilgi edinin.

Point In Polygon algoritması

JavaScript'te bir noktanın poligonun içinde olup olmadığını hesaplamanın birçok yolu vardır. İşte bir noktanın bir poligonun içinde mi yoksa dışında mı olduğunu belirlemek için ışın izleme algoritması kullanan iyi bilinen bir uygulamadan C'ye aktarılmış bir örnek. Bu algoritma, sonsuza kadar uzayan bir çizginin şeklin sınırını kaç kez geçtiğini sayarak bunu belirler. Yalnızca birkaç satır kod gerekir:

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

JavaScript'e taşıma

Bu algoritmanın JavaScript sürümü şu şekilde görünür:

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

BigQuery'de Standart SQL kullanılırken UDF yaklaşımı için yalnızca tek bir ifade gerekir ancak UDF, ifadede geçici bir işlev olarak tanımlanmalıdır. Örneğin, Aşağıdaki SQL ifadesini Sorgu Düzenleyici penceresine yapıştırın.

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

Tebrikler!

Artık BigQuery'yi kullanarak üç tür coğrafi sorgu çalıştırdınız. Gördüğünüz gibi, konum bu veri kümesine yönelik sorguların sonuç verilerinde büyük bir fark yaratıyor ancak sorgularınızı nerede çalıştıracağınızı tahmin etmediğiniz sürece yalnızca SQL sorgularını kullanarak mekansal kalıpları anlık olarak keşfetmek zor.

Verileri harita üzerinde görselleştirebilseydik ve ilgi alanlarını tanımlayarak verileri keşfedebilseydik! Google Haritalar API'lerini kullanarak tam olarak bunu yapabilirsiniz. Öncelikle Haritalar API'yi etkinleştirmeniz, yerel makinenizde çalışan basit bir web sayfası oluşturmanız ve web sayfanızdan sorgu göndermek için BigQuery API'yi kullanmaya başlamanız gerekir.

4. Google Haritalar API'leriyle çalışma

Bazı basit mekansal sorgular çalıştırdıktan sonraki adım, kalıpları görmek için çıkışı görselleştirmektir. Bunu yapmak için Maps API'yi etkinleştirecek, haritadan BigQuery'ye sorgu gönderen bir web sayfası oluşturacak ve ardından sonuçları haritada çizeceksiniz.

Maps JavaScript API'yi etkinleştirme

Bu Codelab'de, projenizde Google Haritalar Platformu'nun Maps JavaScript API'sini etkinleştirmeniz gerekir. Bunu yapmak için aşağıdakileri yapın:

  1. Google Cloud Platform Console'da Marketplace'e gidin.
  2. Marketplace'te "Maps JavaScript API"yi arayın.
  3. Arama sonuçlarında Maps JavaScript API kutucuğunu tıklayın.
  4. "Etkinleştir" düğmesini tıklayın.

API anahtarı oluşturma

Google Haritalar Platformu'na istek göndermek için bir API anahtarı oluşturmanız ve bu anahtarı tüm isteklerle birlikte göndermeniz gerekir. API anahtarı oluşturmak için şunları yapın:

  1. Google Cloud Platform Console'da hamburger menüyü tıklayarak sol gezinme çubuğunu açın.
  2. "API'ler ve Hizmetler" > "Kimlik Bilgileri"'ni seçin.
  3. "Kimlik bilgisi oluştur" düğmesini tıklayın ve ardından "API anahtarı"nı seçin.
  4. Yeni API anahtarını kopyalama

Kodu indirme ve web sunucusu kurma

Bu codelab'in tüm kodunu indirmek için aşağıdaki düğmeyi tıklayın:

İndirilen ZIP dosyasını açın. Bu işlem, ihtiyacınız olacak tüm kaynaklarla birlikte bu codelab'in her adımı için bir klasör içeren bir kök klasörü (bigquery) açar.

stepN klasörleri, bu codelab'in her adımının istenen son durumunu içerir. Bunlar referans amaçlıdır. Tüm kodlama çalışmalarımızı work adlı dizinde yapacağız.

Yerel web sunucusu kurma

Kendi web sunucunuzu kullanmakta serbest olsanız da bu codelab, Chrome Web Sunucusu ile iyi çalışacak şekilde tasarlanmıştır. Bu uygulama henüz yüklü değilse Chrome Web Mağazası'ndan yükleyebilirsiniz.

Yüklendikten sonra uygulamayı açın. Chrome'da bunu şu şekilde yapabilirsiniz:

  1. Chrome'u açın.
  2. En üstteki adres çubuğuna chrome://apps yazın.
  3. Enter tuşuna basın
  4. Açılan pencerede Web Sunucusu simgesini tıklayın. Bir uygulamayı sağ tıklayarak normal veya sabitlenmiş sekmede, tam ekranda ya da yeni pencerede de açabilirsiniz. a3ed00e79b8bfee7.png Ardından, yerel web sunucunuzu yapılandırmanıza olanak tanıyan şu iletişim kutusunu görürsünüz: 81b6151c3f60c948.png
  5. "KLASÖR SEÇ"i tıklayın ve codelab örnek dosyalarını indirdiğiniz konumu seçin.
  6. "Seçenekler" bölümünde, "index.html dosyasını otomatik olarak göster" seçeneğinin yanındaki kutuyu işaretleyin: 17f4913500faa86f.png
  7. Web sunucusunu durdurmak ve yeniden başlatmak için "Web Sunucusu: BAŞLATILDI" etiketli açma/kapatma düğmesini sola, ardından tekrar sağa kaydırın.

a5d554d0d4a91851.png

5. Harita ve çizim araçları yükleniyor

Temel bir harita sayfası oluşturma

Maps JavaScript API'yi ve birkaç satır JavaScript'i kullanarak Google Haritası yükleyen basit bir HTML sayfasıyla başlayın. Google Haritalar Platformu'nun Simple Map Sample (Basit Harita Örneği) bölümündeki kod, başlamak için harika bir yerdir. Bu dosya, istediğiniz metin düzenleyiciye veya IDE'ye kopyalayıp yapıştırmanız için burada yeniden oluşturulmuştur. Ayrıca, indirdiğiniz depodan index.html simgesini açarak da bulabilirsiniz.

  1. index.html dosyasını, deponun yerel kopyasındaki work klasörüne kopyalayın.
  2. img/ klasörünü, deponun yerel kopyasındaki work/ klasörüne kopyalayın.
  3. Metin düzenleyicinizde veya IDE'nizde work/index.html dosyasını açın.
  4. YOUR_API_KEY kısmını daha önce oluşturduğunuz API anahtarıyla değiştirin.
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
    async defer></script>
  1. Tarayıcınızda localhost:<port>/work adresini açın. Burada port, yerel web sunucunuzun yapılandırmasında belirtilen bağlantı noktası numarasıdır. Varsayılan bağlantı noktası 8887'dır. İlk haritalarınız gösterilir.

Tarayıcıda bir hata mesajı alırsanız API anahtarınızın doğru olduğundan ve yerel web sunucunuzun etkin olduğundan emin olun.

Varsayılan konumu ve yakınlaştırma düzeyini değiştirme

Konumu ve yakınlaştırma düzeyini ayarlayan kod, index.html dosyasının 27. ve 28. satırlarında yer alıyor ve şu anda Avustralya'nın Sidney şehrine odaklanmış durumda:

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

Bu eğitimde New York'taki taksi yolculuğu verileri kullanılıyor. Bu nedenle, harita başlatma kodunu New York City'deki bir konuma uygun bir yakınlaştırma düzeyinde (13 veya 14 iyi sonuç verir) ortalayacak şekilde değiştireceksiniz.

Bunun için yukarıdaki kod bloğunu, haritayı Empire State binasının ortasına hizalamak ve yakınlaştırma düzeyini 14 olarak ayarlamak üzere aşağıdaki şekilde güncelleyin:

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

Ardından, sonuçları görmek için tarayıcınızda haritayı yeniden yükleyin.

Çizim ve görselleştirme kitaplıklarını yükleme

Haritanıza çizim özellikleri eklemek için Maps JavaScript API'yi yükleyen komut dosyasını, Google Haritalar Platformu'na çizim kitaplığını etkinleştirmesini söyleyen isteğe bağlı bir parametre ekleyerek değiştirirsiniz.

Bu codelab'de HeatmapLayer da kullanılıyor. Bu nedenle, görselleştirme kitaplığını istemek için komut dosyasını da güncelleyeceksiniz. Bunu yapmak için libraries parametresini ekleyin ve visualization ile drawing kitaplıklarını virgülle ayrılmış değerler olarak belirtin (ör.libraries=visualization,drawing).

Aşağıdaki gibi görünmelidir:

<script src='http://maps.googleapis.com/maps/api/js?libraries=visualization,drawing&callback=initMap&key=YOUR_API_KEY' async defer></script>

DrawingManager'ı ekleyin

Kullanıcı tarafından çizilen şekilleri sorguya giriş olarak kullanmak için Circle, Rectangle ve Polygon araçları etkinleştirilmişken haritanıza DrawingManager simgesini ekleyin.

Tüm DrawingManager kurulum kodunu yeni bir işleve yerleştirmeniz önerilir. Bu nedenle, index.html dosyanızın kopyasında aşağıdakileri yapın:

  1. setUpDrawingTools() işlevini oluşturmak ve map özelliğini sayfadaki harita nesnesine referans verecek şekilde ayarlamak için aşağıdaki kodu kullanarak setUpDrawingTools() adlı bir işlev ekleyin.DrawingManager

google.maps.drawing.DrawingManager(options) öğesine iletilen seçenekler, çizilen şekiller için varsayılan şekil çizme türünü ve görüntüleme seçeneklerini ayarlar. Haritanın sorgu olarak gönderilecek alanlarını seçmek için şekillerin opaklığı sıfır olmalıdır. Kullanılabilir seçenekler hakkında daha fazla bilgi için DrawingManager Seçenekleri başlıklı makaleyi inceleyin.

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. Harita nesnesi oluşturulduktan sonra setUpDrawingTools() işlevinizde initMap() işlevini çağırın.
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 40.744593, lng: -73.990370}, // Manhattan, New York.
    zoom: 12
  });

  setUpDrawingTools();
}
  1. index.html dosyasını yeniden yükleyin ve çizim araçlarının görünür olduğundan emin olun. Ayrıca, bu araçlarla daire, dikdörtgen ve poligon şekilleri çizebildiğinizden emin olun.

Daire ve dikdörtgen çizmek için tıklayıp sürükleyebilirsiniz ancak poligonlar her tepe noktası için tıklanarak ve şekli tamamlamak için çift tıklanarak çizilmelidir.

Çizim Etkinliklerini İşleme

Bir kullanıcının şekil çizmeyi bitirdiğinde tetiklenen etkinlikleri işlemek için bir koda ihtiyacınız vardır. Tıpkı SQL sorguları oluşturmak için çizilen şekillerin koordinatlarına ihtiyacınız olduğu gibi.

Bununla ilgili kodu daha sonraki bir adımda ekleyeceğiz ancak şimdilik rectanglecomplete, circlecomplete ve polygoncomplete etkinliklerini işlemek için üç boş etkinlik işleyici oluşturacağız. İşleyicilerin bu aşamada herhangi bir kod çalıştırması gerekmez.

setUpDrawingTools() işlevinizin en altına aşağıdakileri ekleyin:

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

Bu kodun çalışan bir örneğini, deponun yerel kopyasındaki step2 klasöründe (step2/map.html) bulabilirsiniz.

6. BigQuery Client API'yi kullanma

Google BigQuery Client API, istek oluşturmak, yanıtları ayrıştırmak ve kimlik doğrulamayı işlemek için gereken çok sayıda standart kodu yazmaktan kaçınmanıza yardımcı olur. Bu codelab'de, tarayıcı tabanlı bir uygulama geliştireceğimiz için BigQuery API, Google APIs Client Library for JavaScript üzerinden kullanılmaktadır.

Ardından, bu API'yi bir web sayfasına yüklemek ve BigQuery ile etkileşim kurmak için kullanmak üzere kod ekleyeceksiniz.

JavaScript için Google Client API'yi ekleme

BigQuery'ye karşı sorgu çalıştırmak için Google Client API for Javascript'i kullanacaksınız. index.html kopyanızda (work klasörünüzde), API'yi aşağıdaki gibi bir <script> etiketi kullanarak yükleyin. Etiketi, Maps API'yi yükleyen <script> etiketinin hemen altına yerleştirin:

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

Google Client API'yi yükledikten sonra kullanıcının BigQuery'deki verilere erişmesine izin verin. Bunu yapmak için OAuth 2.0'ı kullanabilirsiniz. Öncelikle Google Cloud Console projenizde bazı kimlik bilgilerini ayarlamanız gerekir.

OAuth 2.0 kimlik bilgileri oluşturma

  1. Google Cloud Console'daki gezinme menüsünde API'ler ve Hizmetler > Kimlik Bilgileri'ni seçin.

Kimlik bilgilerinizi ayarlayabilmeniz için uygulamanızın son kullanıcısının, uygulamanızı kendi adına BigQuery verilerine erişmesi için yetkilendirirken göreceği yetkilendirme ekranıyla ilgili bazı yapılandırmalar eklemeniz gerekir.

Bunu yapmak için OAuth izin ekranı sekmesini tıklayın. 2. Bu jetonun kapsamlarına BigQuery API'yi eklemeniz gerekir. Google API'leri için Kapsamlar bölümünde Kapsam Ekle düğmesini tıklayın. 3. Listede, ../auth/bigquery kapsamına sahip BigQuery API girişinin yanındaki kutuyu işaretleyin. 4. Ekle'yi tıklayın. 5. "Uygulama adı" alanına bir ad girin. 6. Ayarlarınızı kaydetmek için Kaydet'i tıklayın. 7. Ardından OAuth istemci kimliğinizi oluşturacaksınız. Bunu yapmak için Kimlik bilgileri oluştur'u tıklayın:

4d18a965fc760e39.png

  1. Açılır menüde OAuth istemci kimliği'ni tıklayın. 1f8b36a1c27c75f0.png
  2. Uygulama Türü bölümünde Web uygulaması'nı seçin.
  3. Uygulama Adı alanına projeniz için bir ad yazın. Örneğin, "BigQuery ve Haritalar".
  4. Kısıtlamalar bölümündeki Yetkilendirilmiş JavaScript Kaynakları alanına, bağlantı noktası numaraları da dahil olmak üzere localhost'un URL'sini girin. Örneğin: http://localhost:8887
  1. Oluştur düğmesini tıklayın.

Bir pop-up pencerede istemci kimliği ve istemci gizli anahtarı gösterilir. BigQuery'ye karşı kimlik doğrulama işlemi gerçekleştirmek için istemci kimliğine ihtiyacınız vardır. Kodu kopyalayıp work/index.html alanına clientId adlı yeni bir genel JavaScript değişkeni olarak yapıştırın.

let clientId = 'YOUR_CLIENT_ID';

7. Yetkilendirme ve başlatma

Web sayfanızın, haritayı başlatmadan önce kullanıcının BigQuery'ye erişmesine izin vermesi gerekir. Bu örnekte, JavaScript Client API dokümanlarının yetkilendirme bölümünde açıklandığı gibi OAuth 2.0 kullanılmaktadır. Sorgu göndermek için OAuth istemci kimliğini ve proje kimliğinizi kullanmanız gerekir.

Google Client API web sayfasına yüklendiğinde aşağıdaki adımları uygulamanız gerekir:

  • Kullanıcıyı yetkilendirin.
  • Yetkilendirildiyse BigQuery API'yi yükleyin.
  • Haritayı yükleyin ve başlatın.

Tamamlanmış HTML sayfasının nasıl görüneceğine dair bir örnek için step3/map.html sayfasına bakın.

Kullanıcıyı yetkilendirme

Uygulamanın son kullanıcısının, uygulama adına BigQuery'deki verilere erişmesi için uygulamayı yetkilendirmesi gerekir. JavaScript için Google Client API, bunu yapmak üzere OAuth mantığını işler.

Gerçek dünyadaki bir uygulamada yetkilendirme adımını nasıl entegre edeceğiniz konusunda birçok seçeneğiniz vardır.

Örneğin, bir düğme gibi bir kullanıcı arayüzü öğesinden authorize() işlevini çağırabilir veya sayfa yüklendiğinde bunu yapabilirsiniz. Burada, gapi.load() yönteminde bir geri çağırma işlevi kullanarak JavaScript için Google Client API yüklendikten sonra kullanıcıyı yetkilendirmeyi seçtik.

Kullanıcının kimliğini hemen doğrulayabilmemiz için hem istemci kitaplığını hem de kimlik doğrulama modülünü yüklemek üzere, JavaScript için Google Client API'yi yükleyen <script> etiketinin hemen sonrasına bazı kodlar yazın.

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

Yetkilendirme sırasında BigQuery API'yi yükleyin.

Kullanıcı yetkilendirildikten sonra BigQuery API'yi yükleyin.

Öncelikle, önceki adımda eklediğiniz clientId değişkeniyle gapi.auth.authorize() işlevini çağırın. Yanıtı handleAuthResult adlı bir geri arama işlevinde işleyin.

immediate parametresi, kullanıcıya pop-up gösterilip gösterilmeyeceğini kontrol eder. Kullanıcı zaten yetkilendirilmişse yetkilendirme pop-up'ını bastırmak için true olarak ayarlayın.

Sayfanıza handleAuthResult() adlı bir işlev ekleyin. Fonksiyonun, kullanıcının başarıyla yetkilendirilip yetkilendirilmediğine bağlı olarak mantık akışını kontrol etmenizi sağlayacak bir authresult parametresi alması gerekir.

Ayrıca, kullanıcı başarıyla yetkilendirildiyse BigQuery API'yi yüklemek için loadApi adlı bir işlev ekleyin.

handleAuthResult() işlevine, işleve authResult nesnesi iletilirse ve nesnenin error özelliği false değerine sahipse loadApi() işlevini çağırma mantığı ekleyin.

loadApi() işlevine, gapi.client.load() yöntemini kullanarak BigQuery API'yi yükleyecek kodu ekleyin.

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

Haritayı yükleme

Son adım, haritayı başlatmaktır. Bunu yapmak için mantık sırasını biraz değiştirmeniz gerekir. Şu anda Maps API JavaScript yüklendiğinde başlatılır.

Bunu, gapi.client nesnesindeki load() yönteminden sonra then() yönteminden initMap() işlevini çağırarak yapabilirsiniz.

// Load BigQuery client API
function loadApi(){
  gapi.client.load('bigquery', 'v2').then(
   () => initMap()
  );
}

8. BigQuery API kavramları

BigQuery API çağrıları genellikle saniyeler içinde yürütülür ancak hemen yanıt döndürmeyebilir. Uzun süren işlerin durumunu öğrenmek için BigQuery'yi yoklamanız ve sonuçları yalnızca iş tamamlandığında getirmeniz gerekir.

Bu adımdaki kodun tamamı step4/map.html dosyasında yer alır.

İstek gönderme

API'yi kullanarak sorgu göndermek için work/index.html dosyasına bir JavaScript işlevi, sorgulanacak tabloyu içeren BigQuery veri kümesinin ve projenin değerlerini depolamak için bazı değişkenler ve ücretlendirilecek proje kimliği ekleyin.

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

İşin durumunu kontrol etme

Aşağıdaki checkJobStatus işlevi, get API yöntemi ve orijinal sorgu isteği tarafından döndürülen jobId kullanılarak bir işin durumunun periyodik olarak nasıl kontrol edileceğini gösterir. İş tamamlanana kadar her 500 milisaniyede bir çalışan bir örnek aşağıda verilmiştir.

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

sendQuery yöntemini, request.execute() çağrısında geri çağırma olarak checkJobStatus() yöntemini çağıracak şekilde değiştirin. İş kimliğini checkJobStatus öğesine iletin. Bu, yanıt nesnesi tarafından jobReference.jobId olarak gösterilir.

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

Sorgu sonuçlarını alma

Bir sorgu çalışmayı tamamladığında sonuçlarını almak için jobs.getQueryResults API çağrısını kullanın. Sayfanıza getQueryResults() adlı bir işlev ekleyin. Bu işlev, jobId parametresini kabul eder:

function getQueryResults(jobId){
  let request = gapi.client.bigquery.jobs.getQueryResults({
    'projectId': billingProjectId,
    'jobId': jobId
  });
  request.execute(response => {
    // Do something with the results.
  })
}

9. BigQuery API ile konum verilerini sorgulama

BigQuery'deki verilere karşı coğrafi sorgular çalıştırmak için SQL'i kullanmanın üç yolu vardır:

BigQuery eski SQL referansının "Gelişmiş Örnekler" bölümündeki Matematiksel İşlevler kısmında sınırlayıcı kutu ve yarıçap sorgularına ilişkin örnekler yer alır.

Sınırlayıcı kutu ve yarıçap sorguları için BigQuery API query yöntemini çağırabilirsiniz. Her sorgu için SQL'i oluşturun ve önceki adımda oluşturduğunuz sendQuery işlevine iletin.

Bu adımdaki kodun çalışan bir örneği step4/map.html dosyasında yer alır.

Dikdörtgen sorguları

BigQuery verilerini haritada göstermenin en basit yolu, enlem ve boylamın bir dikdörtgen içinde olduğu tüm satırları, "küçüktür" ve "büyüktür" karşılaştırması kullanarak istemektir. Bu, mevcut harita görünümü veya haritada çizilen bir şekil olabilir.

Kullanıcı tarafından çizilen bir şekli kullanmak için index.html içindeki kodu, bir dikdörtgen tamamlandığında tetiklenen çizim etkinliğini işleyecek şekilde değiştirin. Bu örnekte kod, dikdörtgenin kapsamını harita koordinatlarında temsil eden bir nesne almak için dikdörtgen nesnesinde getBounds() kullanır ve bunu rectangleQuery adlı bir işleve iletir:

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

rectangleQuery işlevinin, BigQuery tablonuzdaki her satırla karşılaştırma yapmak için sağ üst (kuzeydoğu) ve sol alt (güneybatı) koordinatlarını kullanması yeterlidir. Burada, konum değerlerini depolayan 'pickup_latitude' ve 'pickup_longitude' adlı sütunlara sahip bir tabloyu sorgulayan bir örnek verilmiştir.

BigQuery tablosunu belirtme

BigQuery API'yi kullanarak bir tabloya sorgu göndermek için SQL sorgunuzda tablonun adını tam nitelikli biçimde sağlamanız gerekir. Standart SQL'deki biçim project.dataset.tablename şeklindedir. Eski SQL'de project.dataset.tablename.

NYC taksi yolculuklarıyla ilgili birçok tablo mevcuttur. Bunları görmek için BigQuery web konsoluna gidin ve "public datasets" (ortak veri kümeleri) menü öğesini genişletin. new_york adlı veri kümesini bulup tabloları görmek için genişletin. Sarı taksi yolculukları tablosunu seçin: bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2016).

Proje kimliğini belirtme

API çağrısında, faturalandırma amacıyla Google Cloud Platform projenizin adını belirtmeniz gerekir. Bu codelab'de bu, tabloyu içeren projeyle aynı proje değildir. Veri yükleyerek kendi projenizde oluşturduğunuz bir tabloyla çalışıyorsanız bu proje kimliği, SQL ifadenizdekiyle aynı olur.

Sorguladığınız tabloyu içeren herkese açık veri kümeleri projesine, tablo adına ve veri kümesi adına referansları tutmak için kodunuza JavaScript değişkenleri ekleyin. Ayrıca kendi faturalandırma proje kimliğinize başvurmak için ayrı bir değişkene ihtiyacınız vardır.

index.html dosyanızın kopyasına billingProjectId, publicProjectId, datasetId ve tableName adlı genel JavaScript değişkenleri ekleyin.

'publicProjectId', 'datasetId' ve 'tableName' değişkenlerini BigQuery Public Datasets projesindeki ayrıntılarla başlatın. billingProjectId öğesini kendi proje kimliğinizle (bu codelab'in "Başlangıç" bölümünde oluşturduğunuz kimlik) başlatın.

let billingProjectId = 'YOUR_PROJECT_ID';
let publicProjectId = 'bigquery-public-data';
let datasetId = 'new_york_taxi_trips';
let tableName = 'tlc_yellow_trips_2016';

Şimdi kodunuza iki işlev ekleyerek SQL oluşturun ve önceki adımda oluşturduğunuz sendQuery işlevini kullanarak sorguyu BigQuery'ye gönderin.

İlk işlev rectangleSQL() olarak adlandırılmalı ve iki bağımsız değişken kabul etmelidir. Bunlar, harita koordinatlarında dikdörtgenin köşelerini temsil eden bir google.Maps.LatLng nesnesi çiftidir.

İkinci işlev rectangleQuery() olarak adlandırılmalıdır. Bu işlem, sorgu metnini sendQuery işlevine iletir.

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

Bu noktada, kullanıcı tarafından çizilen bir dikdörtgenin içerdiği tüm satırlar için BigQuery'ye sorgu gönderecek kadar kodunuz var. Daireler ve serbest çizim şekilleri için başka sorgu yöntemleri eklemeden önce, sorgudan dönen verilerin nasıl işleneceğine bakalım.

10. Yanıtı görselleştirme

BigQuery tabloları çok büyük olabilir (petabaytlarca veri) ve saniyede yüz binlerce satır artabilir. Bu nedenle, haritada çizilebilmesi için döndürülen veri miktarını sınırlamaya çalışmak önemlidir. Çok büyük bir sonuç kümesindeki (on binlerce satır veya daha fazla) her satırın konumunun çizilmesi, okunamaz bir haritayla sonuçlanır. Hem SQL sorgusunda hem de haritada konumları toplamak için birçok teknik vardır ve bir sorgunun döndüreceği sonuçları sınırlayabilirsiniz.

Bu adımın tam kodu step5/map.html adresinde mevcuttur.

Bu codelab'de web sayfanıza aktarılan veri miktarını makul bir boyutta tutmak için rectangleSQL() işlevini, yanıtı 10.000 satırla sınırlayan bir ifade ekleyecek şekilde değiştirin. Aşağıdaki örnekte bu, tüm sorgu işlevlerinin aynı değeri kullanabilmesi için recordLimit adlı bir genel değişkende belirtilmiştir.

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

Konum yoğunluğunu görselleştirmek için ısı haritası kullanabilirsiniz. Maps JavaScript API'de bu amaçla kullanılan bir HeatmapLayer sınıfı vardır. HeatmapLayer, enlem ve boylam koordinatlarından oluşan bir dizi alır. Bu nedenle, sorgudan döndürülen satırları ısı haritasına dönüştürmek oldukça kolaydır.

getQueryResults işlevinde, response.result.rows dizisini ısı haritası oluşturacak doHeatMap() adlı yeni bir JavaScript işlevine iletin.

Her satırda, sütun dizisi olan f adlı bir özellik bulunur. Her sütunda değeri içeren bir v özelliği bulunur.

Kodunuzun, her satırdaki sütunlarda döngü oluşturması ve değerleri ayıklaması gerekir.

SQL sorgusunda yalnızca taksi yolcularının alındığı yerlerin enlem ve boylam değerlerini istediğiniz için yanıtta yalnızca iki sütun bulunur.

Konum dizisini ısı haritası katmanına atadığınızda setMap() işlevini çağırmayı unutmayın. Bu işlem, öğenin haritada görünmesini sağlar.

Aşağıda bununla ilgili bir örnek verilmiştir:

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

Bu noktada şunları yapabilmeniz gerekir:

  • Sayfayı açın ve BigQuery'ye göre yetkilendirin.
  • New York'ta bir yere dikdörtgen çizme
  • Elde edilen sorgu sonuçlarını ısı haritası olarak görselleştirilmiş şekilde görün.

2016 NYC Yellow Taxi verilerine karşı yapılan bir dikdörtgen sorgusunun sonuçlarına ait ısı haritası örneğini burada bulabilirsiniz. Bu görselde, Temmuz ayında bir Cumartesi günü Empire State Binası çevresindeki teslim alma noktalarının dağılımı gösterilmektedir:

7b1face0e7c71c78.png

11. Bir nokta etrafındaki yarıçapa göre sorgulama

Yarıçap sorguları çok benzer. BigQuery'nin eski SQL matematik işlevlerini kullanarak, yeryüzünde dairesel bir alanı yaklaşık olarak hesaplayan Haversine Formülü'nü kullanan bir SQL sorgusu oluşturabilirsiniz.

Dikdörtgenler için kullanılan aynı tekniği kullanarak, kullanıcı tarafından çizilen bir dairenin merkezini ve yarıçapını almak için OverlayComplete etkinliğini işleyebilir ve sorgu için SQL'i aynı şekilde oluşturabilirsiniz.

Bu adım için kodun çalışan bir örneği, kod deposunda step6/map.html olarak yer almaktadır.

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

index.html dosyanızın kopyasına iki yeni boş işlev ekleyin: circleQuery() ve haversineSQL().

Ardından, circlecomplete adlı yeni bir işleve merkezi ve yarıçapı ileten bir etkinlik işleyici ekleyin.circleQuery().

circleQuery() işlevi, sorgu için SQL oluşturmak üzere haversineSQL() işlevini çağırır ve ardından aşağıdaki örnek kodda gösterildiği gibi sendQuery() işlevini çağırarak sorguyu gönderir.

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

Deneyin!

Yukarıdaki kodu ekleyin ve haritanın bir bölümünü seçmek için "Daire" aracını kullanmayı deneyin. Sonuç aşağıdaki gibi görünmelidir:

845418166b7cc7a3.png

12. Rastgele şekilleri sorgulama

Özet: SQL, dikdörtgen ve daire dışında rastgele şekiller kullanılarak sorgulama yapılmasını desteklemez. BigQuery'de yerel bir geometri veri türü yoktur. Bu nedenle, çokgen şekiller kullanarak sorgu çalıştırmak için basit SQL sorgularından farklı bir yaklaşım kullanmanız gerekir.

Bu amaçla kullanılabilecek çok güçlü bir BigQuery özelliği, kullanıcı tanımlı işlevlerdir (UDF). Kullanıcı tanımlı işlevler, SQL sorgusunun içinde JavaScript kodu yürütür.

Bu adım için çalışan kod step7/map.html dosyasındadır.

BigQuery API'deki kullanıcı tanımlı işlevler

Kullanıcı tanımlı işlevler için BigQuery API yaklaşımı, web konsolundan biraz farklıdır: jobs.insert method işlevini çağırmanız gerekir.

API üzerinden Standart SQL sorgularında, kullanıcı tanımlı işlev kullanmak için tek bir SQL ifadesi yeterlidir. useLegacySql değeri false olarak ayarlanmalıdır. Aşağıdaki JavaScript örneğinde, yeni bir iş eklemek için istek nesnesi oluşturan ve gönderen bir işlev gösterilmektedir. Bu örnekte, kullanıcı tanımlı işlev içeren bir sorgu kullanılmıştır.

Bu yaklaşımla ilgili çalışan bir örneği step7/map.html adresinde bulabilirsiniz.

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

SQL sorgusu şu şekilde oluşturulur:

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

Burada iki şey oluyor. Öncelikle kod, belirli bir noktanın bir poligonun içinde olup olmadığını belirlemek için JavaScript kodunu kapsayan CREATE TEMPORARY FUNCTION ifadesini oluşturur. Çokgen koordinatları, x,y koordinat çiftlerinden oluşan bir JavaScript dizisini dizeye dönüştürmek için JSON.stringify(poly) yöntem çağrısı kullanılarak eklenir. Çokgen nesnesi, SQL'i oluşturan işleve bağımsız değişken olarak iletilir.

İkinci olarak, kod ana SQL SELECT ifadesini oluşturur. Bu örnekte, UDF WHERE ifadesinde çağrılır.

Maps API ile entegrasyon

Bunu Maps API çizim kitaplığıyla kullanmak için kullanıcının çizdiği poligonu kaydetmemiz ve SQL sorgusunun UDF bölümüne iletmemiz gerekir.

Öncelikle, şeklin koordinatlarını boylam ve enlem çiftleri dizisi olarak almak için polygoncomplete çizim etkinliğini ele almamız gerekir:

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

polygonQuery işlevi, UDF JavaScript işlevlerini dize olarak ve UDF işlevini çağıracak SQL ifadesini oluşturabilir.

Bunun çalışan bir örneği için step7/map.html dosyasına bakın.

Örnek çıkış

Serbest çizim poligon kullanılarak BigQuery'deki 2016 NYC TLC Yellow Taxi verilerinden alınan sonuçların sorgulanmasıyla ilgili bir örnek aşağıda verilmiştir. Seçilen veriler ısı haritası olarak çizilir.

Screen Shot 2017-05-09 at 10.00.48 AM.png

13. Daha İleriye Gitme

Bu codelab'i genişleterek verilerin diğer yönlerini incelemek için bazı öneriler aşağıda verilmiştir. Bu fikirlerin çalışan bir örneğini kod deposundaki step8/map.html adresinde bulabilirsiniz.

Eşleme bırakma

Şu ana kadar yalnızca teslim alma konumlarını haritalandırdık. dropoff_latitude ve dropoff_longitude sütunlarını isteyip ısı haritası kodunu bunları çizecek şekilde değiştirerek belirli bir konumda başlayan taksi yolculuklarının varış noktalarını görebilirsiniz.

Örneğin, Empire State Binası civarında yolcu alma isteğinde bulunan kişileri taksilerin genellikle nereye bıraktığına bakalım.

Teslim alma konumuna ek olarak bu sütunları istemek için polygonSql() bölümündeki SQL ifadesinin kodunu değiştirin.

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

Ardından doHeatMap işlevi, bırakma değerlerini kullanabilir. Sonuç nesnesinin, dizideki bu sütunların konumunu bulmak için incelenebilecek bir şeması vardır. Bu durumda, dizin konumları 2 ve 3 olur. Bu dizinler, kodu daha yönetilebilir hale getirmek için bir değişkenden okunabilir. Isı haritasının maxIntensity, piksel başına maksimum 20 bırakma yoğunluğunu gösterecek şekilde ayarlanmıştır.

Isı haritası verileri için hangi sütunları kullandığınızı değiştirmenize olanak tanıyan bazı değişkenler ekleyin.

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

Aşağıda, 2016'da Empire State Binası'nın çevresindeki tüm teslim alma noktalarından yapılan bırakma işlemlerinin dağılımını gösteren bir ısı haritası yer almaktadır. Özellikle Times Meydanı çevresinde ve 23. Cadde ile 14. Cadde arasındaki 5. Cadde boyunca büyük yoğunluklar (kırmızı noktalar) görebilirsiniz. Bu yakınlaştırma düzeyinde gösterilmeyen diğer yüksek yoğunluklu yerler arasında La Guardia ve JFK havalimanları, Dünya Ticaret Merkezi ve Battery Park yer alır.

Screen Shot 2017-05-09 at 10.40.01 AM.png

Temel haritayı stilize etme

Maps JavaScript API'yi kullanarak bir Google Haritası oluşturduğunuzda, JSON nesnesi kullanarak harita stilini ayarlayabilirsiniz. Veri görselleştirmelerinde haritadaki renkleri kapatmak faydalı olabilir. mapstyle.withgoogle.com adresindeki Google Maps API Stil Sihirbazı'nı kullanarak harita stilleri oluşturabilir ve deneyebilirsiniz.

Harita nesnesini başlatırken veya daha sonraki herhangi bir zamanda harita stili ayarlayabilirsiniz. initMap() işlevine özel stil ekleme:

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

Aşağıdaki örnek stilde, ilgi çekici yer etiketleri içeren bir gri tonlamalı harita gösterilmektedir.

[
  {
    "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"
      }
    ]
  }
]

Kullanıcıya geri bildirim verme

BigQuery genellikle saniyeler içinde yanıt verse de sorgu çalışırken kullanıcıya bir şeyler olduğunu göstermek bazen yararlı olur.

Web sayfanıza checkJobStatus() işlevinin yanıtını gösteren bir kullanıcı arayüzü ve sorgunun devam ettiğini belirten animasyonlu bir grafik ekleyin.

Görüntüleyebileceğiniz bilgiler arasında sorgu süresi, döndürülen veri miktarı ve işlenen veri miktarı yer alır.

Sorgu tarafından döndürülen satır sayısını, sorgunun ne kadar sürdüğünü ve işlenen veri miktarını gösterecek bir panel oluşturmak için haritanın <div> sonrasına biraz HTML ekleyin.

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

Bu panelin görünümü ve konumu CSS tarafından kontrol edilir. Aşağıdaki snippet'te gösterildiği gibi, paneli harita türü düğmelerinin ve çizim araç çubuğunun altındaki sayfanın sol üst köşesine yerleştirmek için CSS ekleyin.

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

Animasyonlu grafik sayfaya eklenebilir ancak gerekene kadar gizlenebilir. BigQuery işi çalışırken grafiği göstermek için bazı JavaScript ve CSS kodları kullanılır.

Animasyonlu grafik göstermek için HTML ekleyin. Kod deposundaki img klasöründe loader.gif adlı bir resim dosyası var.

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

Resmi konumlandırmak ve gerekene kadar varsayılan olarak gizlemek için biraz CSS ekleyin.

#spinner {
  position: absolute; 
  top: 50%; 
  left: 50%; 
  margin-left: -32px; 
  margin-top: -32px; 
  opacity: 0; 
  z-index: -1000;
}

Son olarak, durum panelini güncellemek ve bir sorgu çalıştırıldığında grafiği göstermek veya gizlemek için biraz JavaScript ekleyin. Hangi bilgilerin mevcut olduğuna bağlı olarak paneli güncellemek için response nesnesini kullanabilirsiniz.

Mevcut bir işi kontrol ederken kullanabileceğiniz bir response.statistics özelliği vardır. İş tamamlandığında response.totalRows ve response.totalBytesProcessed özelliklerine erişebilirsiniz. Kullanıcı için, aşağıdaki kod örneğinde gösterildiği gibi milisaniyeleri saniyeye, baytları ise gigabayta dönüştürmek faydalıdır.

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

Bir checkJobStatus() çağrısına yanıt verildiğinde ve sorgu sonuçları getirildiğinde bu yöntemi çağırın. Örneğin:

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

Animasyonlu grafiği açıp kapatmak için görünürlüğünü kontrol eden bir işlev ekleyin. Bu işlev, kendisine iletilen tüm HTML DOM öğelerinin opaklığını değiştirir.

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

Son olarak, sorguyu işlemeden önce ve sorgu sonucu BigQuery'den döndükten sonra bu yöntemi çağırın.

Bu kod, kullanıcı dikdörtgen çizmeyi bitirdiğinde fadeToggle işlevini çağırır.

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

Sorgu yanıtı alındığında animasyonlu grafiği gizlemek için fadeToggle() işlevini tekrar çağırın.

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

Sayfa aşağıdaki gibi görünmelidir.

Screen Shot 2017-05-10 at 2.32.19 PM.png

step8/map.html adresindeki tam örneğe göz atın.

14. Dikkate Alınması Gereken Noktalar

Çok Fazla İşaretçi Var

Çok büyük tablolarla çalışıyorsanız sorgunuz, haritada verimli bir şekilde görüntülenemeyecek kadar çok satır döndürebilir. WHERE ifadesi veya LIMIT ifadesi ekleyerek sonuçları sınırlayın.

Çok sayıda işaretçi çizmek haritanın okunmasını zorlaştırabilir. Yoğunluğu göstermek için HeatmapLayer kullanabilir veya kümelerdeki veri noktalarının konumunu belirtmek için kümeleri işaretleyebilirsiniz. Daha fazla ayrıntıyı işaretçi kümeleme eğitimimizde bulabilirsiniz.

Sorguları Optimize Etme

BigQuery, her sorguda tablonun tamamını tarar. BigQuery kota kullanımınızı optimize etmek için sorgunuzda yalnızca ihtiyacınız olan sütunları seçin.

Enlem ve boylamı dizeler yerine kayan nokta olarak saklarsanız sorgular daha hızlı olur.

İlginç Sonuçları Dışa Aktarma

Buradaki örneklerde, son kullanıcının BigQuery tablosuyla kimliğinin doğrulanması gerekir. Bu durum her kullanım alanına uygun olmayabilir. İlginç kalıplar keşfettiğinizde, sonuçları BigQuery'den dışa aktarıp Google Haritalar Veri Katmanı'nı kullanarak statik bir veri kümesi oluşturarak bunları daha geniş bir kitleyle paylaşmak daha kolay olabilir.

Google Haritalar Platformu Hizmet Şartları'nı göz önünde bulundurun. Google Haritalar Platformu fiyatlandırması hakkında daha fazla bilgi için online belgelere göz atın.

Daha Fazla Veriyle Oynayın!

BigQuery'de enlem ve boylam sütunlarına sahip çeşitli herkese açık veri kümeleri vardır. Örneğin, 2009-2016 yılları arasındaki NYC Taxi veri kümeleri, Uber ve Lyft NYC yolculuk verileri ve GDELT veri kümesi.

15. Tebrikler!

Bu sayede, BigQuery tablolarında bazı coğrafi sorgular çalıştırarak hızlıca kullanmaya başlayabilir, kalıpları keşfedip Google Harita'da görselleştirebilirsiniz. Keyifli harita oluşturma deneyimi dileriz.

Sırada ne var?

Google Haritalar Platformu veya BigQuery hakkında daha fazla bilgi edinmek isterseniz aşağıdaki önerilere göz atın.

Google'ın sunucusuz, petabayt ölçeğinde veri ambarı hizmeti hakkında daha fazla bilgi edinmek için BigQuery nedir? başlıklı makaleyi inceleyin.

BigQuery API'yi kullanarak basit bir uygulama oluşturma ile ilgili nasıl yapılır kılavuzuna göz atın.

Kullanıcı etkileşimini etkinleştirerek Google Haritası'nda şekil çizme hakkında daha fazla bilgi için Çizim kitaplığı geliştirici kılavuzu'na bakın.

Google Harita'da verileri görselleştirmenin diğer yollarına göz atın.

Client API'yi kullanarak diğer Google API'lerine erişmenin temel kavramlarını anlamak için JavaScript Client API'si için Başlangıç Kılavuzu'na bakın.