Catch up on everything we announced at this year's Firebase Summit. Learn more

Cloud Firestore'da varlık oluşturun

Oluşturduğunuz uygulamanın türüne bağlı olarak, hangi kullanıcılarınızın veya cihazlarınızın aktif olarak çevrimiçi olduğunu saptamayı yararlı bulabilirsiniz - aksi halde "varlığı algılama" olarak da bilinir.

Örneğin, bir sosyal ağ gibi bir uygulama oluşturuyorsanız veya bir IoT cihazı filosu dağıtıyorsanız, çevrimiçi ve ücretsiz sohbet eden arkadaşlarınızın bir listesini görüntülemek veya IoT cihazlarınızı "son görülme tarihine göre sıralamak" için bu bilgileri kullanabilirsiniz. "

Cloud Firestore, varlığı yerel olarak desteklemez, ancak bir varlık sistemi oluşturmak için diğer Firebase ürünlerinden yararlanabilirsiniz.

Çözüm: Gerçek Zamanlı Veritabanı ile Bulut İşlevleri

Cloud Firestore'u Firebase Realtime Database'in yerel varlık özelliğine bağlamak için Cloud Functions'ı kullanın.

Bağlantı durumunu bildirmek için Realtime Database'i kullanın, ardından bu verileri Cloud Firestore'a yansıtmak için Cloud Functions'ı kullanın.

Gerçek Zamanlı Veritabanında varlığı kullanma

İlk olarak, Realtime Database'de geleneksel bir varlık sisteminin nasıl çalıştığını düşünün.

// Fetch the current user's ID from Firebase Authentication.
var uid = firebase.auth().currentUser.uid;

// Create a reference to this user's specific status node.
// This is where we will store data about being online/offline.
var userStatusDatabaseRef = firebase.database().ref('/status/' + uid);

// We'll create two constants which we will write to 
// the Realtime database when this device is offline
// or online.
var isOfflineForDatabase = {
    state: 'offline',
    last_changed: firebase.database.ServerValue.TIMESTAMP,
};

var isOnlineForDatabase = {
    state: 'online',
    last_changed: firebase.database.ServerValue.TIMESTAMP,
};

// Create a reference to the special '.info/connected' path in 
// Realtime Database. This path returns `true` when connected
// and `false` when disconnected.
firebase.database().ref('.info/connected').on('value', function(snapshot) {
    // If we're not currently connected, don't do anything.
    if (snapshot.val() == false) {
        return;
    };

    // If we are currently connected, then use the 'onDisconnect()' 
    // method to add a set which will only trigger once this 
    // client has disconnected by closing the app, 
    // losing internet, or any other means.
    userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() {
        // The promise returned from .onDisconnect().set() will
        // resolve as soon as the server acknowledges the onDisconnect() 
        // request, NOT once we've actually disconnected:
        // https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect

        // We can now safely set ourselves as 'online' knowing that the
        // server will mark us as offline once we lose connection.
        userStatusDatabaseRef.set(isOnlineForDatabase);
    });
});

Bu örnek, eksiksiz bir Gerçek Zamanlı Veritabanı varlık sistemidir. Birden fazla bağlantı kesilmesini, çökmeyi vb. yönetir.

Cloud Firestore'a bağlanma

Cloud Firestore'da benzer bir çözümü uygulamak için aynı Realtime Database kodunu kullanın, ardından Realtime Database ve Cloud Firestore'u senkronize tutmak için Cloud Functions'ı kullanın.

Zaten yapmadıysanız, eklemek Gerçek Zamanlı Veritabanı projenize ve yukarıdaki varlığı çözümünü içermektedir.

Ardından, aşağıdaki yöntemlerle iletişim durumunu Cloud Firestore ile senkronize edeceksiniz:

  1. Yerel olarak, uygulamanın çevrimdışı olduğunu bilmesi için çevrimdışı cihazın Cloud Firestore önbelleğine.
  2. Global olarak, Cloud Firestore'a erişen diğer tüm cihazların bu belirli cihazın çevrimdışı olduğunu bilmesi için bir Bulut İşlevi kullanmak.

Cloud Firestore'un yerel önbelleğini güncelleme

İlk sayıyı yerine getirmek için gereken değişikliklere bir göz atalım - Cloud Firestore'un yerel önbelleğini güncelleme.

// ...
var userStatusFirestoreRef = firebase.firestore().doc('/status/' + uid);

// Firestore uses a different server timestamp value, so we'll 
// create two more constants for Firestore state.
var isOfflineForFirestore = {
    state: 'offline',
    last_changed: firebase.firestore.FieldValue.serverTimestamp(),
};

var isOnlineForFirestore = {
    state: 'online',
    last_changed: firebase.firestore.FieldValue.serverTimestamp(),
};

firebase.database().ref('.info/connected').on('value', function(snapshot) {
    if (snapshot.val() == false) {
        // Instead of simply returning, we'll also set Firestore's state
        // to 'offline'. This ensures that our Firestore cache is aware
        // of the switch to 'offline.'
        userStatusFirestoreRef.set(isOfflineForFirestore);
        return;
    };

    userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() {
        userStatusDatabaseRef.set(isOnlineForDatabase);

        // We'll also add Firestore set here for when we come online.
        userStatusFirestoreRef.set(isOnlineForFirestore);
    });
});

Bu değişikliklerle birlikte artık yerel Bulut Firestore devlet daima cihazın çevrimiçi / çevrimdışı durumlarını yansıtacak olduğunu garanti ederiz. Eğer dinleyebilirsiniz Bu araçlar /status/{uid} Belge ve verileri kullanmak bağlantı durumunu yansıtacak şekilde UI değiştirmek için.

userStatusFirestoreRef.onSnapshot(function(doc) {
    var isOnline = doc.data().state == 'online';
    // ... use isOnline
});

Cloud Firestore'u küresel olarak güncelleme

Uygulamamız çevrimiçi varlığı kendisine doğru bir şekilde bildirse de, "çevrimdışı" durum yazma işlemimiz yalnızca yerel olduğundan ve bir bağlantı yeniden kurulduğunda eşitlenmeyeceğinden, bu durum diğer Cloud Firestore uygulamalarında henüz doğru olmayacaktır. Bunu engellemek için, biz saatler Bulut İşlevini kullanacağız status/{uid} Gerçek Zamanlı Veritabanında yolunu. Realtime Database değeri değiştiğinde, tüm kullanıcıların durumlarının doğru olması için değer Cloud Firestore ile senkronize edilir.

Node.js

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

// Since this code will be running in the Cloud Functions environment
// we call initialize Firestore without any arguments because it
// detects authentication from the environment.
const firestore = admin.firestore();

// Create a new function which is triggered on changes to /status/{uid}
// Note: This is a Realtime Database trigger, *not* Firestore.
exports.onUserStatusChanged = functions.database.ref('/status/{uid}').onUpdate(
    async (change, context) => {
      // Get the data written to Realtime Database
      const eventStatus = change.after.val();

      // Then use other event data to create a reference to the
      // corresponding Firestore document.
      const userStatusFirestoreRef = firestore.doc(`status/${context.params.uid}`);

      // It is likely that the Realtime Database change that triggered
      // this event has already been overwritten by a fast change in
      // online / offline status, so we'll re-read the current data
      // and compare the timestamps.
      const statusSnapshot = await change.after.ref.once('value');
      const status = statusSnapshot.val();
      functions.logger.log(status, eventStatus);
      // If the current timestamp for this data is newer than
      // the data that triggered this event, we exit this function.
      if (status.last_changed > eventStatus.last_changed) {
        return null;
      }

      // Otherwise, we convert the last_changed field to a Date
      eventStatus.last_changed = new Date(eventStatus.last_changed);

      // ... and write it to Firestore.
      return userStatusFirestoreRef.set(eventStatus);
    });

Bu işlevi dağıttığınızda, Cloud Firestore ile çalışan eksiksiz bir varlık sisteminiz olur. Aşağıda çevrimiçi veya bir kullanarak çevrimdışı herhangi bir kullanıcı için izleme örneğidir where() sorgusu.

firebase.firestore().collection('status')
    .where('state', '==', 'online')
    .onSnapshot(function(snapshot) {
        snapshot.docChanges().forEach(function(change) {
            if (change.type === 'added') {
                var msg = 'User ' + change.doc.id + ' is online.';
                console.log(msg);
                // ...
            }
            if (change.type === 'removed') {
                var msg = 'User ' + change.doc.id + ' is offline.';
                console.log(msg);
                // ...
            }
        });
    });

sınırlamalar

Cloud Firestore uygulamanıza varlık eklemek için Realtime Database'i kullanmak ölçeklenebilir ve etkilidir ancak bazı sınırlamaları vardır:

  • Zıplamaölçer - Bulut Firestore değişiklikleri hatta gerçek-zamanlı dinlerken, bu çözüm birden değişiklikleri tetikleyecek muhtemeldir. Bu değişiklikler istediğinizden daha fazla olayı tetiklerse Cloud Firestore olaylarını manuel olarak iptal edin.
  • Bağlantı - değil Bulut Firestore için Gerçek Zamanlı Veri Tabanına bu uygulama tedbirleri bağlantısı,. Her bir veritabanına bağlantı durumu aynı değilse, bu çözüm yanlış bir iletişim durumu bildirebilir.
  • Android - Android, hareketsizlik 60 saniye sonra arka sunucudan Gerçek Zamanlı Veri Tabanı keser üzerinde. Hareketsizlik, açık dinleyici veya bekleyen işlem olmadığı anlamına gelir. Bağlantı açık tutmak, size yanında bir yola bir değer olay dinleyicisi eklemek önerilen .info/connected . Örneğin Yapabileceğin FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() her oturumun başında. Daha fazla bilgi için, bkz Algılama Bağlantı Durumu .