Cloud Firestore Web Codelab

Hedefler

Bu codelab olarak, tarafından desteklenen bir restoran tavsiye web uygulaması inşa edeceğiz Bulut Firestore .

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:

Bir Firebase projesi oluşturun

  1. In Firebase konsoluna , ardından Ekle projeyi tıklayın Firebase proje FriendlyEats isim.

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

  1. Proje oluşturma tıklayın.

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

  • Firebase Kimlik kolayca kullanıcıları tanımlamak
  • Bulut Firestore Cloud üzerinde yapılandırılmış verileri kaydetmek ve veri güncellendiğinde anında bildirim almak için
  • Firebase statik varlıklar ana bilgisayara Barındırma ve hizmet

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. Biz Anonim oturum kullanacağız - Kullanıcı sessizce sorulmadan imzalanacak anlamına gelir.

Sen Anonim girişini etkinleştirmek gerekir.

  1. Firebase konsolunda, sol gezinme Oluştur bölümünü bulun.
  2. Kimlik tıklayın, ardından Oturum açma yöntemi sekmesine tıklayın (veya buraya tıklayın doğrudan oraya gitmek).
  3. Anonim Oturum Açma Sağlayıcısı etkinleştirme, 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. Okumak için çekinmeyin Anonim Kimlik belgelerine daha fazla bilgi edinmek.

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 Yapı bölümünde, Firestore veritabanı. Bulut Firestore bölmesinde veritabanı oluşturun 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. Gelen Kuralları sekmesinin Firebase konsolunun aşağıdaki kuralları ekleyebilir ve daha sonra Yayınla 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.

Klon GitHub depo komut satırından:

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

Örnek kod 📁 içine klonlanmış olması gereken friendlyeats-web dizininde. Ş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 (WebStorm, Atom, Sublime, Visual Studio kod ...) açık kullanma veya 📁 ithal friendlyeats-web dizini. 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.

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, ardından Firebase projeyi bir takma ad vermek, Project kimliğini seçin.

Takma ad, birden çok ortamınız (üretim, hazırlama, vb.) varsa kullanışlıdır. Ancak, bu codelab için, 'adil diğer adını kullanmasına izin default .

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

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

Biz kullanıyoruz Firebase Barındırma lokal bizim app hizmet etmek emülatör. Web uygulaması bugünden itibaren kullanılabilir olmalıdır http: // localhost: 5000 .

  1. Adresinden uygulamasını açın http: // localhost: 5000 .

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

Bu bölümde, uygulamanın kullanıcı arayüzünü doldurabilmemiz için Cloud Firestore'a bazı veriler yazacağız. Bu yoluyla elle yapılabilir Firebase konsoluna , ama biz de temel Bulut Firestore yazma göstermek için uygulamanın kendisindeki yapacağım.

Veri örneği

Firestore verileri koleksiyonlara, belgelere, alanlara ve alt koleksiyonlara bölünür. Biz denilen bir üst düzey koleksiyonunda bir belge olarak her restoran saklayacaktır restaurants .

img3.png

Daha sonra, adlı bir subcollection her gözden saklamak edeceğiz ratings her restoranın altında.

img4.png

Firestore'a restoran ekleyin

Uygulamamızdaki ana model nesnesi bir restorandır. Diyelim bir restoran belgeyi ekler bazı kod yazmak restaurants koleksiyonu.

  1. İndirilen dosyalar, açık itibaren scripts/FriendlyEats.Data.js .
  2. Fonksiyon bulun FriendlyEats.prototype.addRestaurant .
  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 için yeni bir belge ekler restaurants koleksiyonu. Belge verileri, düz bir JavaScript nesnesinden gelir. Önce bir bulut Firestore koleksiyonu bir başvuru alarak bunu restaurants sonra add veri ing'.

Restoranları ekleyelim!

  1. Tarayıcınızda FriendlyEats uygulamanıza geri dönün ve yenileyin.
  2. Tıklayın Mock Verilerini ekleyin.

Uygulama otomatik olarak o zaman, restoranlar nesneleri rastgele kümesi üretmek için arayacak addRestaurant işlevi. Biz hala veri (codelab sonraki bölümü) alınırken uygulamak gerekir çünkü Ancak, henüz gerçek bir web uygulamasında verileri görmez.

Eğer giderseniz Bulut Firestore sekmesi Firebase konsolunda olsa da, artık yeni belgeleri görmelisiniz restaurants koleksiyonu!

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.

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. Dosya geri dön scripts/FriendlyEats.Data.js .
  2. Fonksiyon bulun FriendlyEats.prototype.getAllRestaurants .
  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, biz üst düzey toplama adında 50 restoranlar kadar alır bir sorgu oluşturmak restaurants ortalama puanı (şu anda tüm sıfır) göre sıralanır. Bu sorguyu ilan etmesinden sonra, biz onu geçmek getDocumentsInQuery() yükleme ve veri işleme sorumludur yöntemle.

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

  1. Dosya geri dön scripts/FriendlyEats.Data.js .
  2. Fonksiyon bulun FriendlyEats.prototype.getDocumentsInQuery .
  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 sonucu bir değişiklik varsa her zaman onun geri arama tetikler.

  • Bütün anlam - İlk kez, geri arama sorgunun tüm sonuç kümesinin ile tetiklenir restaurants Bulut Firestore dan koleksiyon. Daha sonra tüm bireysel belgeleri geçer renderer.display fonksiyonu.
  • Bir belge silindiğinde, change.type eşittir removed . 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 gidip 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

Şimdiye kadar, nasıl kullanılacağı gösterdik onSnapshot güncellemeleri gerçek zamanlı olarak almak için; Ancak, her zaman istediğimiz 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. Dosyanızı geri dön scripts/FriendlyEats.Data.js .
  2. Fonksiyon bulun FriendlyEats.prototype.getRestaurant .
  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ıkladığınızda restoranın ayrıntılar sayfasını görmelisiniz:

img1.png

Kod laboratuvarında daha sonra derecelendirme eklemeyi uygulamamız gerekeceğinden, şimdilik derecelendirme ekleyemezsiniz.

Ş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 bütün getirmesi basit sorgusuna bir örnek Dim Sum restoranlar:

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

Adından da anlaşılacağı gibi, where() metodu bizim sorgu indir alanları belirlediğimiz kısıtlamaları karşılamak koleksiyonun sadece üyeler yapacaktır. Nerede bu durumda, sadece restoranlar indirirsiniz category olan Dim Sum .

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. Dosyanızı geri dön scripts/FriendlyEats.Data.js .
  2. Fonksiyon bulun FriendlyEats.prototype.getFilteredRestaurants .
  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 çoklu ekler where filtre ve tek orderBy maddesi kullanıcı girişi temel bir bileşik, sorgu oluşturmak için. Sorgumuz artık yalnızca kullanıcının gereksinimlerine uyan 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.

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 aynı anda kolayca dağıtabiliriz.

  1. Uygulamanızın indirilen yerel dizinde, bir bulacağınız firestore.indexes.json dosyasını.

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.

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 verdiyse, 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. İlk kendisini sahiptir yorumu sunulmak üzere, daha sonra restoranın değerlendirme count ve average rating ihtiyacı güncellenmesi. 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, verilerimizin tutarlı kalmasını sağlayarak tek bir atomik işlemde birden çok okuma ve yazma gerçekleştirmemize olanak tanıyan işlem işlevselliği sağlar.

  1. Dosyanızı geri dön scripts/FriendlyEats.Data.js .
  2. Fonksiyon bulun FriendlyEats.prototype.addRating .
  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, biz sayısal değerlerini güncellemek için bir işlem tetikler avgRating ve numRatings restoran belgede. Aynı zamanda, biz yeni ekle rating için ratings subcollection.

Bu kod laboratuvarının 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şikliğini önlemek için çok daha ayrıntılı kurallar belirlemek isteriz.

  1. Firebase konsolunun Yapı bölümünde, Firestore veritabanı.
  2. Bulut Firestore bölümünde Kuralları sekmesini tıklayın (veya buraya tıklayın doğrudan oraya gitmek).
  3. Aşağıdaki kurallara varsayılan değiştirin ve ardından Yayınla'yı tıklayın.

firestore.kurallar

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. Firestore.rules sizin çalışma dizinde dosya zaten yukarıdan kurallar içeriyor. 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

Bu kod laboratuvarında, Cloud Firestore ile temel ve gelişmiş okuma ve yazma işlemlerini nasıl gerçekleştireceğinizi ve güvenlik kurallarıyla veri erişimini nasıl güvence altına alacağınızı öğrendiniz. Sen tam bir çözüm bulabilirsiniz ilgili hızlı başlangıç-js depo .

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