Bulut Firestore Web Codelab

1. Genel Bakış

Hedefler

Bu kod laboratuvarında, Cloud Firestore tarafından desteklenen bir restoran önerisi 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 Kimlik Doğrulaması 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'yi tıklayın, ardından Firebase projesini FriendlyEats olarak adlandırın.

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
  • Yapılandırılmış verileri Buluta 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 Barındırma

Bu özel codelab için Firebase Barındırma'yı 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 Kimlik Doğrulamayı Etkinleştir

Kimlik doğrulama bu codelab'in odak noktası olmasa da, uygulamamızda bir tür kimlik doğrulamaya sahip olmak önemlidir. Anonim giriş kullanacağız - bu, kullanıcıya sorulmadan sessizce oturum açacağı anlamına gelir.

Anonim oturum açmayı etkinleştirmeniz gerekecek.

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

img7.png

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

Cloud Firestore'u etkinleştirin

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

Cloud Firestore'u etkinleştirmeniz gerekecek. Firebase konsolunun Oluşturma bölümünde, Firestore Veritabanı'nı 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ıtlar, bu da 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ı kod laboratuvarında daha sonra iyileştireceğiz.

3. Örnek kodu alın

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

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

Örnek kod, 📁 friendlyeats-web dizinine klonlanmış olmalıdır. Bundan sonra, 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 tavsiyesi uygulamasından oluşan codelab için başlangıç ​​kodunu içerir. Bu kod laboratuvarı boyunca onu işlevsel hale getireceğiz, böylece 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 yüklendiğini doğrulayın:
firebase --version

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

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

Uygulamanızın Firebase Barındırma yapılandırmasını uygulamanızın yerel dizininden ve dosyalarından çekmek için web uygulaması şablonunu 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.

Birden çok ortamınız varsa (üretim, hazırlama vb.) bir takma ad kullanışlıdır. Ancak, bu codelab 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 gerçekten ç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 Barındırma ö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ısını göstermek için uygulamanın kendisinde yapacağız.

Veri örneği

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

img3.png

Daha sonra her yorumu, her restoranın altındaki 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 bazı kodlar 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 koleksiyon 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 onu 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 çağıracaktır. Ancak, verileri alma işlemini gerçekleştirmemiz gerektiğinden (kod laboratuvarının bir sonraki bölümü) verileri henüz gerçek web uygulamanızda görmeyeceksiniz .

Ancak Firebase konsolundaki Cloud Firestore sekmesine giderseniz, artık restaurants koleksiyonunda yeni belgeler görmelisiniz!

img6.png

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

Bir sonraki bölümde, Cloud Firestore'dan verileri nasıl alacağınızı ve bunları 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 bunları 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 önce, varsayılan, filtrelenmemiş restoran listesine hizmet edecek 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, ortalama derecelendirmeye göre (şu anda tamamı sıfır) sıralanan ve restaurants adlı üst düzey koleksiyondan en fazla 50 restoranı alacak bir sorgu oluşturuyoruz. Bu sorguyu tanımladıktan sonra, verilerin yüklenmesinden ve işlenmesinden sorumlu olan getDocumentsInQuery() yöntemine iletiyoruz.

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 aramasını tetikleyecektir.

  • İlk kez, geri arama, sorgunun tüm sonuç kümesiyle, yani Cloud Firestore'dan tüm restaurants koleksiyonuyla tetiklenir. Daha sonra tüm belgeleri renderer.display işlevine aktarır.
  • Bir belge silindiğinde, change.type removed eşittir. Yani 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() verileri

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

Bir kullanıcı, uygulamanızdaki belirli bir restoranı tıkladığında tetiklenen bir yöntem uygulamak istiyoruz.

  1. scripts/FriendlyEats.Data.js dosyanıza 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ın sayfalarını görüntüleyebileceksiniz. Listedeki bir restorana tıklamanız yeterlidir ve restoranın ayrıntılar sayfasını görmelisiniz:

img1.png

Şimdilik, daha sonra codelab'de derecelendirme eklemeyi uygulamamız gerektiğinden, derecelendirme ekleyemezsiniz.

9. Verileri sıralayın ve filtreleyin

Şu anda, uygulamamız bir restoran listesi gösteriyor, ancak kullanıcının ihtiyaçlarına göre filtreleme yapması mümkün değil. Bu bölümde, filtrelemeyi etkinleştirmek için Cloud Firestore'un gelişmiş sorgulama özelliğini 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ıtlamalara uyan koleksiyonun üyelerini indirmesini sağlar. Bu durumda, yalnızca category Dim Sum olan restoranları indirir.

Uygulamamızda kullanıcı, "San Francisco'da Pizza" veya "Los Angeles'ta Popülerliğe Göre Sıralanan Deniz Ürünleri" gibi belirli sorgular oluşturmak için birden çok filtreyi zincirleyebilir.

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

  1. scripts/FriendlyEats.Data.js dosyanıza 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ı girişine dayalı olarak bileşik bir sorgu oluşturmak için birden fazla 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ürecektir.

FriendlyEats uygulamanızı tarayıcınızda yenileyin, ardından fiyat, şehir ve kategoriye göre filtreleme yapabileceğinizi doğrulayın. Test sırasında, tarayıcınızın JavaScript Konsolunda şuna benzeyen hatalar göreceksiniz:

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

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ı olmasını sağlar.

Hata mesajındaki bağlantının açılması, Firebase konsolunda dizin oluşturma kullanıcı arayüzünü otomatik olarak doğru parametrelerle birlikte açacaktır. Bir sonraki bölümde, bu uygulama için gereken dizinleri yazıp konuşlandıracağı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 aynı anda kolayca dağıtabiliriz.

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

Bu dosya, olası tüm 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 yayında olacak ve hata mesajları kaybolacaktır.

11. Bir işlemde veri yazın

Bu bölümde, kullanıcıların restoranlara yorum gönderme olanağını ekleyeceğiz. Şimdiye kadar, tüm yazılarımız atomik ve nispeten basitti. Bunlardan herhangi biri hatalıysa, büyük olasılıkla 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 yazmayı koordine etmemiz gerekecek. Öncelikle incelemenin kendisinin gönderilmesi gerekir, ardından restoranın puan count ve average rating güncellenmesi gerekir. Bunlardan biri başarısız olursa, diğeri başarısız olursa, veritabanımızın bir bölümündeki verilerin başka bir bölümdeki 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 izin vererek verilerimizin tutarlı kalmasını sağlayan işlem işlevselliği sağlar.

  1. scripts/FriendlyEats.Data.js dosyanıza 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üvenceye alın

Bu codelab'in başlangıcında, uygulamamızın güvenlik kurallarını, veritabanını herhangi bir okumaya veya yazmaya 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 Oluşturma bölümünde, Firestore Veritabanı'nı 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 belgesinde yapılan güncellemeler yalnızca derecelendirmeleri değiştirebilir, adı veya diğer değişmez verileri değiştiremez.
  • Derecelendirmeler, yalnızca kullanıcı kimliği oturum açmış kullanıcıyla eşleşirse oluşturulabilir, bu da kimlik sahtekarlığını ö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 gelen kuralları içerir. Bu kuralları yerel dosya sisteminizden dağıtmak için (Firebase konsolunu kullanmak yerine) aşağıdaki komutu çalıştırmanız gerekir:

firebase deploy --only firestore:rules

13. Sonuç

Bu kod laboratuvarında, Cloud Firestore ile temel ve gelişmiş okuma ve yazma işlemlerinin nasıl gerçekleştirileceğini ve güvenlik kurallarıyla veri erişiminin nasıl güvenli hale getirileceğini öğrendiniz. Tam çözümü quickstarts-js deposunda bulabilirsiniz.

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