Bulut Firestore Web Codelab

1. Genel Bakış

Hedefler

Bu kod laboratuvarında, Cloud Firestore tarafından desteklenen bir restoran tavsiyesi web uygulaması oluşturacaksınız.

img5.png

ne öğreneceksin

  • Bir web uygulamasından Cloud Firestore'a veri okuma ve yazma
  • Cloud Firestore verilerindeki değişiklikleri gerçek zamanlı olarak dinleyin
  • Cloud Firestore verilerinin güvenliğini sağlamak için Firebase Authentication ve güvenlik kurallarını kullanın
  • Karmaşık Cloud Firestore sorguları yazın

Neye ihtiyacın olacak

Bu codelab'i başlatmadan önce şunları yüklediğinizden emin olun:

2. Bir Firebase projesi oluşturun ve kurun

Bir Firebase projesi oluşturun

  1. Firebase konsolunda , Proje ekle'ye tıklayın, ardından Firebase projesine FriendlyEats adını verin.

Firebase projeniz için Proje Kimliğini unutmayın.

  1. Proje oluştur 'u tıklayın.

Oluşturacağımız uygulama, web'de bulunan birkaç Firebase hizmetini kullanıyor:

  • Kullanıcılarınızı kolayca tanımlamak için Firebase Authentication
  • Bulutta yapılandırılmış verileri kaydetmek ve veriler güncellendiğinde anında bildirim almak için Cloud Firestore
  • Statik varlıklarınızı barındırmak ve sunmak için Firebase Hosting

Bu özel kod laboratuvarı için Firebase Hosting'i zaten yapılandırdık. Ancak, Firebase Auth ve Cloud Firestore için, Firebase konsolunu kullanarak hizmetlerin yapılandırılması ve etkinleştirilmesi konusunda size yol göstereceğiz.

Anonim Yetkilendirmeyi Etkinleştir

Kimlik doğrulama bu kod laboratuvarının odak noktası olmasa da, uygulamamızda bir tür kimlik doğrulamanın olması önemlidir. Anonim oturum açmayı kullanacağız - bu, kullanıcının sorulmadan sessizce oturum açacağı anlamına gelir.

Anonim oturum açmayı etkinleştirmeniz gerekecek.

  1. Firebase konsolunda, sol gezinme bölmesinde Oluştur bölümünü bulun.
  2. Kimlik Doğrulama 'yı tıklayın, ardından Oturum açma yöntemi sekmesini tıklayın (veya doğrudan oraya gitmek için burayı tıklayın ).
  3. Anonim Oturum Açma Sağlayıcısını etkinleştirin ve ardından Kaydet 'i tıklayın.

img7.png

Bu, uygulamanın kullanıcılarınız web uygulamasına eriştiklerinde sessizce oturum açmasına olanak tanır. Daha fazla bilgi edinmek için Anonim Kimlik Doğrulama belgelerini okumaktan çekinmeyin.

Cloud Firestore'u Etkinleştir

Uygulama, restoran bilgilerini ve derecelendirmelerini kaydetmek ve almak için Cloud Firestore'u kullanır.

Cloud Firestore'u etkinleştirmeniz gerekecek. Firebase konsolunun Oluştur bölümünde, Firestore Database öğesine tıklayın. Cloud Firestore bölmesinde Veritabanı oluştur'a tıklayın.

Cloud Firestore'daki verilere erişim, Güvenlik Kuralları tarafından kontrol edilir. Bu kod laboratuvarında daha sonra kurallar hakkında daha fazla konuşacağız, ancak başlamak için önce verilerimiz üzerinde bazı temel kurallar belirlememiz gerekiyor. Firebase konsolunun Kurallar sekmesinde aşağıdaki kuralları ekleyin ve ardından Yayınla 'yı tıklayın.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

Yukarıdaki kurallar, oturum açmış kullanıcıların veri erişimini kısıtlayarak, kimliği doğrulanmamış kullanıcıların okumasını veya yazmasını engeller. Bu, genel erişime izin vermekten daha iyidir, ancak yine de güvenli olmaktan uzaktır, bu kuralları daha sonra kod laboratuvarında iyileştireceğiz.

3. Örnek kodu alın

GitHub deposunu komut satırından klonlayın:

git clone https://github.com/firebase/friendlyeats-web

Örnek kod, 📁 friendlyeats-web dizinine kopyalanmış olmalıdır. Şu andan itibaren, tüm komutlarınızı bu dizinden çalıştırdığınızdan emin olun:

cd friendlyeats-web

Başlangıç ​​uygulamasını içe aktarın

IDE'nizi (WebStorm, Atom, Sublime, Visual Studio Code...) kullanarak 📁 friendlyeats-web dizinini açın veya içe aktarın. Bu dizin, henüz işlevsel olmayan bir restoran öneri uygulamasından oluşan kod laboratuvarı için başlangıç ​​kodunu içerir. Bu kod laboratuvarı boyunca onu işlevsel hale getireceğiz, bu nedenle yakında o dizindeki kodu düzenlemeniz gerekecek.

4. Firebase Komut Satırı Arayüzünü Kurun

Firebase Komut Satırı Arayüzü (CLI), web uygulamanızı yerel olarak sunmanıza ve web uygulamanızı Firebase Hosting'e dağıtmanıza olanak tanır.

  1. Aşağıdaki npm komutunu çalıştırarak CLI'yi kurun:
npm -g install firebase-tools
  1. Aşağıdaki komutu çalıştırarak CLI'nin doğru şekilde kurulduğunu doğrulayın:
firebase --version

Firebase CLI sürümünün v7.4.0 veya üstü olduğundan emin olun.

  1. Aşağıdaki komutu çalıştırarak Firebase CLI'yi yetkilendirin:
firebase login

Web uygulaması şablonunu, uygulamanızın yerel dizininden ve dosyalarından Firebase Hosting için uygulamanızın yapılandırmasını alacak şekilde ayarladık. Ancak bunu yapmak için uygulamanızı Firebase projenizle ilişkilendirmemiz gerekiyor.

  1. Komut satırınızın uygulamanızın yerel dizinine eriştiğinden emin olun.
  2. Aşağıdaki komutu çalıştırarak uygulamanızı Firebase projenizle ilişkilendirin:
firebase use --add
  1. İstendiğinde, Proje Kimliğinizi seçin ve ardından Firebase projenize bir takma ad verin.

Takma ad, birden çok ortamınız (üretim, hazırlama, vb.) varsa kullanışlıdır. Ancak, bu kod laboratuvarı için default takma adını kullanalım.

  1. Komut satırınızdaki kalan talimatları izleyin.

5. Yerel sunucuyu çalıştırın

Uygulamamız üzerinde çalışmaya başlamaya hazırız! Uygulamamızı yerel olarak çalıştıralım!

  1. Aşağıdaki Firebase CLI komutunu çalıştırın:
firebase emulators:start --only hosting
  1. Komut satırınız aşağıdaki yanıtı göstermelidir:
hosting: Local server: http://localhost:5000

Uygulamamızı yerel olarak sunmak için Firebase Hosting öykünücüsünü kullanıyoruz. Web uygulaması artık http://localhost:5000 adresinden erişilebilir olmalıdır.

  1. Uygulamanızı http://localhost:5000 adresinde açın.

Firebase projenize bağlı olan FriendlyEats kopyanızı görmelisiniz.

Uygulama, Firebase projenize otomatik olarak bağlandı ve sizi sessizce anonim bir kullanıcı olarak oturum açtı.

img2.png

6. Cloud Firestore'a veri yazın

Bu bölümde, uygulamanın kullanıcı arayüzünü doldurabilmemiz için Cloud Firestore'a bazı veriler yazacağız. Bu, Firebase konsolu aracılığıyla manuel olarak yapılabilir, ancak temel bir Cloud Firestore yazımı göstermek için bunu uygulamanın kendisinde yapacağız.

Veri örneği

Firestore verileri koleksiyonlara, belgelere, alanlara ve alt koleksiyonlara bölünür. Her restoranı, restaurants adı verilen üst düzey bir koleksiyonda bir belge olarak saklayacağız.

img3.png

Daha sonra, her bir yorumu, her restoranın altında ratings adı verilen bir alt koleksiyonda saklayacağız.

img4.png

Firestore'a restoran ekleyin

Uygulamamızdaki ana model nesnesi bir restorandır. restaurants koleksiyonuna bir restoran belgesi ekleyen bir kod yazalım.

  1. İndirdiğiniz dosyalardan scripts/FriendlyEats.Data.js açın.
  2. FriendlyEats.prototype.addRestaurant işlevini bulun.
  3. Tüm işlevi aşağıdaki kodla değiştirin.

FriendlyEats.Data.js

FriendlyEats.prototype.addRestaurant = function(data) {
  var collection = firebase.firestore().collection('restaurants');
  return collection.add(data);
};

Yukarıdaki kod, restaurants koleksiyonuna yeni bir belge ekler. Belge verileri, düz bir JavaScript nesnesinden gelir. Bunu, önce bir Cloud Firestore koleksiyonu restaurants referans alarak ve ardından verileri add yapıyoruz.

Restoranları ekleyelim!

  1. Tarayıcınızda FriendlyEats uygulamanıza geri dönün ve yenileyin.
  2. Sahte Veri Ekle 'yi tıklayın.

Uygulama otomatik olarak rastgele bir dizi restoran nesnesi oluşturacak ve ardından addRestaurant işlevinizi arayacaktır. Ancak, verileri alma işlemini gerçekleştirmemiz gerektiğinden (codelab'in sonraki bölümü) hala gerçek web uygulamanızda verileri görmeyeceksiniz.

Firebase konsolundaki Cloud Firestore sekmesine giderseniz, şimdi restaurants koleksiyonunda yeni belgeler görmelisiniz!

img6.png

Tebrikler, az önce bir web uygulamasından Cloud Firestore'a veri yazdınız!

Sonraki bölümde, Cloud Firestore'dan nasıl veri alacağınızı ve uygulamanızda nasıl görüntüleyeceğinizi öğreneceksiniz.

7. Cloud Firestore'dan verileri görüntüleyin

Bu bölümde, Cloud Firestore'dan nasıl veri alacağınızı ve uygulamanızda nasıl görüntüleyeceğinizi öğreneceksiniz. İki temel adım, bir sorgu oluşturmak ve bir anlık görüntü dinleyicisi eklemektir. Bu dinleyici, sorguyla eşleşen tüm mevcut verilerden haberdar edilecek ve güncellemeleri gerçek zamanlı olarak alacaktır.

İlk olarak, varsayılan, filtrelenmemiş restoran listesini sunacak sorguyu oluşturalım.

  1. scripts/FriendlyEats.Data.js dosyasına geri dönün.
  2. FriendlyEats.prototype.getAllRestaurants işlevini bulun.
  3. Tüm işlevi aşağıdaki kodla değiştirin.

FriendlyEats.Data.js

FriendlyEats.prototype.getAllRestaurants = function(renderer) {
  var query = firebase.firestore()
      .collection('restaurants')
      .orderBy('avgRating', 'desc')
      .limit(50);

  this.getDocumentsInQuery(query, renderer);
};

Yukarıdaki kodda, restaurants adlı üst düzey koleksiyondan ortalama derecelendirmeye göre sıralanmış (şu anda tümü sıfır) 50'ye kadar restoranı alacak bir sorgu oluşturuyoruz. Bu sorguyu bildirdikten sonra, verileri yüklemekten ve oluşturmaktan sorumlu olan getDocumentsInQuery() yöntemine geçiyoruz.

Bunu bir anlık görüntü dinleyicisi ekleyerek yapacağız.

  1. scripts/FriendlyEats.Data.js dosyasına geri dönün.
  2. FriendlyEats.prototype.getDocumentsInQuery işlevini bulun.
  3. Tüm işlevi aşağıdaki kodla değiştirin.

FriendlyEats.Data.js

FriendlyEats.prototype.getDocumentsInQuery = function(query, renderer) {
  query.onSnapshot(function(snapshot) {
    if (!snapshot.size) return renderer.empty(); // Display "There are no restaurants".

    snapshot.docChanges().forEach(function(change) {
      if (change.type === 'removed') {
        renderer.remove(change.doc);
      } else {
        renderer.display(change.doc);
      }
    });
  });
};

Yukarıdaki kodda, query.onSnapshot , sorgunun sonucunda her değişiklik olduğunda geri çağrısını tetikleyecektir.

  • İlk kez, geri arama, sorgunun tüm sonuç kümesiyle tetiklenir - bu, Cloud Firestore'dan tüm restaurants koleksiyonu anlamına gelir. Daha sonra tüm bireysel belgeleri renderer.display işlevine iletir.
  • Bir belge silindiğinde, change.type , removed eşittir. Bu durumda, restoranı kullanıcı arayüzünden kaldıran bir işlev çağıracağız.

Artık her iki yöntemi de uyguladığımıza göre, uygulamayı yenileyin ve daha önce Firebase konsolunda gördüğümüz restoranların artık uygulamada göründüğünü doğrulayın. Bu bölümü başarıyla tamamladıysanız, uygulamanız artık Cloud Firestore ile veri okuyor ve yazıyor!

Restoran listeniz değiştikçe, bu dinleyici otomatik olarak güncellenmeye devam edecektir. Firebase konsoluna gitmeyi ve bir restoranı manuel olarak silmeyi veya adını değiştirmeyi deneyin; değişikliklerin sitenizde hemen göründüğünü göreceksiniz!

img5.png

8. Get() verisi

Şimdiye kadar, güncellemeleri gerçek zamanlı olarak almak için onSnapshot nasıl kullanılacağını gösterdik; Ancak, istediğimiz her zaman bu değildir. Bazen verileri yalnızca bir kez getirmek daha mantıklıdır.

Bir kullanıcı uygulamanızda belirli bir restoranı tıkladığında tetiklenen bir yöntemi uygulamak isteyeceğiz.

  1. Dosya scripts/FriendlyEats.Data.js geri dönün.
  2. FriendlyEats.prototype.getRestaurant işlevini bulun.
  3. Tüm işlevi aşağıdaki kodla değiştirin.

FriendlyEats.Data.js

FriendlyEats.prototype.getRestaurant = function(id) {
  return firebase.firestore().collection('restaurants').doc(id).get();
};

Bu yöntemi uyguladıktan sonra, her restoran için sayfaları görüntüleyebilirsiniz. Listedeki bir restorana tıklamanız yeterlidir ve restoranın ayrıntılar sayfasını görmelisiniz:

img1.png

Derecelendirme eklemeyi daha sonra codelab'de uygulamamız gerekeceğinden, şimdilik derecelendirme ekleyemezsiniz.

9. Verileri sıralayın ve filtreleyin

Şu anda uygulamamız restoranların bir listesini gösteriyor, ancak kullanıcının ihtiyaçlarına göre filtreleme yapmasının bir yolu yok. Bu bölümde, filtrelemeyi etkinleştirmek için Cloud Firestore'un gelişmiş sorgulamasını kullanacaksınız.

İşte tüm Dim Sum restoranlarını getirmek için basit bir sorgu örneği:

var filteredQuery = query.where('category', '==', 'Dim Sum')

Adından da anlaşılacağı gibi, where() yöntemi, sorgumuzun yalnızca alanları belirlediğimiz kısıtlamaları karşılayan koleksiyonun üyelerini indirmesini sağlar. Bu durumda, yalnızca Dim Sum category olduğu restoranları indirir.

Uygulamamızda kullanıcı, "San Francisco'da Pizza" veya "Popülerlik tarafından sipariş edilen Los Angeles'ta Deniz Ürünleri" gibi belirli sorgular oluşturmak için birden çok filtreyi zincirleyebilir.

Restoranlarımızı kullanıcılarımız tarafından seçilen birden çok kritere göre filtreleyecek bir sorgu oluşturan bir yöntem oluşturacağız.

  1. Dosya scripts/FriendlyEats.Data.js geri dönün.
  2. FriendlyEats.prototype.getFilteredRestaurants işlevini bulun.
  3. Tüm işlevi aşağıdaki kodla değiştirin.

FriendlyEats.Data.js

FriendlyEats.prototype.getFilteredRestaurants = function(filters, renderer) {
  var query = firebase.firestore().collection('restaurants');

  if (filters.category !== 'Any') {
    query = query.where('category', '==', filters.category);
  }

  if (filters.city !== 'Any') {
    query = query.where('city', '==', filters.city);
  }

  if (filters.price !== 'Any') {
    query = query.where('price', '==', filters.price.length);
  }

  if (filters.sort === 'Rating') {
    query = query.orderBy('avgRating', 'desc');
  } else if (filters.sort === 'Reviews') {
    query = query.orderBy('numRatings', 'desc');
  }

  this.getDocumentsInQuery(query, renderer);
};

Yukarıdaki kod, kullanıcı girdisine dayalı bir bileşik sorgu oluşturmak için birden çok where filtresi ve tek bir orderBy yan tümcesi ekler. Sorgumuz artık yalnızca kullanıcının gereksinimleriyle eşleşen restoranları döndürecek.

Tarayıcınızda FriendlyEats uygulamanızı yenileyin, ardından fiyata, şehre ve kategoriye göre filtreleyebildiğinizi doğrulayın. Test ederken, tarayıcınızın JavaScript Konsolunda şuna benzer hatalar göreceksiniz:

The query requires an index. You can create it here: https://console.firebase.google.com/project/.../database/firestore/indexes?create_index=...

Bu hatalar, Cloud Firestore'un çoğu bileşik sorgu için dizin gerektirmesinden kaynaklanır. Sorgularda dizinlerin zorunlu kılınması, Cloud Firestore'un geniş ölçekte hızlı kalmasını sağlar.

Hata mesajındaki bağlantının açılması, Firebase konsolunda dizin oluşturma kullanıcı arayüzünü, doğru parametreler doldurulmuş olarak otomatik olarak açacaktır. Bir sonraki bölümde, bu uygulama için gereken dizinleri yazıp dağıtacağız.

10. Dizinleri dağıtın

Uygulamamızdaki her yolu keşfetmek ve dizin oluşturma bağlantılarının her birini takip etmek istemiyorsak, Firebase CLI'yi kullanarak birçok dizini tek seferde kolayca dağıtabiliriz.

  1. Uygulamanızın indirilen yerel dizininde bir firestore.indexes.json dosyası bulacaksınız.

Bu dosya, tüm olası filtre kombinasyonları için gereken tüm dizinleri açıklar.

firestore.indexes.json

{
 "indexes": [
   {
     "collectionGroup": "restaurants",
     "queryScope": "COLLECTION",
     "fields": [
       { "fieldPath": "city", "order": "ASCENDING" },
       { "fieldPath": "avgRating", "order": "DESCENDING" }
     ]
   },

   ...

 ]
}
  1. Bu dizinleri aşağıdaki komutla dağıtın:
firebase deploy --only firestore:indexes

Birkaç dakika sonra dizinleriniz canlı olacak ve hata mesajları kaybolacaktır.

11. Bir işleme veri yazın

Bu bölümde, kullanıcılara restoranlara yorum gönderme olanağı ekleyeceğiz. Şimdiye kadar, tüm yazılarımız atomik ve nispeten basitti. Bunlardan herhangi biri hata verirse, muhtemelen kullanıcıdan bunları yeniden denemesini isteriz veya uygulamamız yazmayı otomatik olarak yeniden dener.

Uygulamamız, bir restoran için puan eklemek isteyen birçok kullanıcıya sahip olacak, bu nedenle birden fazla okuma ve yazma işlemini koordine etmemiz gerekecek. Önce incelemenin kendisi gönderilmeli, ardından restoranın puan count ve average rating güncellenmelidir. Bunlardan biri başarısız olurken diğeri başarısız olursa, veritabanımızın bir bölümündeki verilerin diğerindeki verilerle eşleşmediği tutarsız bir durumda kalırız.

Neyse ki Cloud Firestore, tek bir atomik işlemde birden çok okuma ve yazma gerçekleştirmemize olanak tanıyan ve verilerimizin tutarlı kalmasını sağlayan işlem işlevselliği sağlar.

  1. Dosya scripts/FriendlyEats.Data.js geri dönün.
  2. FriendlyEats.prototype.addRating işlevini bulun.
  3. Tüm işlevi aşağıdaki kodla değiştirin.

FriendlyEats.Data.js

FriendlyEats.prototype.addRating = function(restaurantID, rating) {
  var collection = firebase.firestore().collection('restaurants');
  var document = collection.doc(restaurantID);
  var newRatingDocument = document.collection('ratings').doc();

  return firebase.firestore().runTransaction(function(transaction) {
    return transaction.get(document).then(function(doc) {
      var data = doc.data();

      var newAverage =
          (data.numRatings * data.avgRating + rating.rating) /
          (data.numRatings + 1);

      transaction.update(document, {
        numRatings: data.numRatings + 1,
        avgRating: newAverage
      });
      return transaction.set(newRatingDocument, rating);
    });
  });
};

Yukarıdaki blokta, restoran belgesindeki avgRating ve numRatings sayısal değerlerini güncellemek için bir işlemi tetikliyoruz. Aynı zamanda, yeni rating ratings alt koleksiyonuna ekliyoruz.

12. Verilerinizi güvence altına alın

Bu codelab'in başında, uygulamamızın güvenlik kurallarını, veritabanını herhangi bir okuma veya yazma işlemine tamamen açacak şekilde belirledik. Gerçek bir uygulamada, istenmeyen veri erişimini veya değiştirilmesini önlemek için çok daha ayrıntılı kurallar belirlemek isteriz.

  1. Firebase konsolunun Oluştur bölümünde, Firestore Database öğesine tıklayın.
  2. Cloud Firestore bölümündeki Kurallar sekmesine tıklayın (veya doğrudan oraya gitmek için buraya tıklayın ).
  3. Varsayılanları aşağıdaki kurallarla değiştirin, ardından Yayınla 'yı tıklayın.

firestore.rules

rules_version = '2';
service cloud.firestore {

  // Determine if the value of the field "key" is the same
  // before and after the request.
  function unchanged(key) {
    return (key in resource.data) 
      && (key in request.resource.data) 
      && (resource.data[key] == request.resource.data[key]);
  }

  match /databases/{database}/documents {
    // Restaurants:
    //   - Authenticated user can read
    //   - Authenticated user can create/update (for demo purposes only)
    //   - Updates are allowed if no fields are added and name is unchanged
    //   - Deletes are not allowed (default)
    match /restaurants/{restaurantId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null;
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys()) 
                    && unchanged("name");
      
      // Ratings:
      //   - Authenticated user can read
      //   - Authenticated user can create if userId matches
      //   - Deletes and updates are not allowed (default)
      match /ratings/{ratingId} {
        allow read: if request.auth != null;
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;
      }
    }
  }
}

Bu kurallar, istemcilerin yalnızca güvenli değişiklikler yapmasını sağlamak için erişimi kısıtlar. Örneğin:

  • Bir restoran belgesindeki güncellemeler, adı veya diğer değişmez verileri değil, yalnızca derecelendirmeleri değiştirebilir.
  • Derecelendirmeler, yalnızca kullanıcı kimliği, oturum açmış olan kullanıcıyla eşleşirse oluşturulabilir, bu da sahtekarlığı önler.

Firebase konsolunu kullanmaya alternatif olarak, Firebase projenize kuralları dağıtmak için Firebase CLI'yi kullanabilirsiniz. Çalışma dizininizdeki firestore.rules dosyası zaten yukarıdan kuralları içerir. Bu kuralları yerel dosya sisteminizden dağıtmak için (Firebase konsolunu kullanmak yerine), aşağıdaki komutu çalıştırırsınız:

firebase deploy --only firestore:rules

13. Sonuç

Bu kod laboratuvarında, Cloud Firestore ile temel ve gelişmiş okuma ve yazma işlemlerini nasıl gerçekleştireceğinizi ve ayrıca güvenlik kurallarıyla veri erişimini nasıl güvence altına alacağınızı öğrendiniz. Tam çözümü quickstarts-js deposunda bulabilirsiniz.

Cloud Firestore hakkında daha fazla bilgi edinmek için aşağıdaki kaynakları ziyaret edin: