สร้างการแสดงข้อมูลใน Cloud Firestore

คุณอาจเห็นว่าการตรวจหาผู้ใช้หรืออุปกรณ์ใดออนไลน์อยู่บ้าง หรือเรียกอีกอย่างว่าการตรวจหา "การปรากฏ" นั่นเอง ทั้งนี้ขึ้นอยู่กับประเภทแอปที่กําลังสร้าง

เช่น หากคุณกำลังสร้างแอปอย่างโซเชียลเน็ตเวิร์กหรือทำให้อุปกรณ์ IoT ใช้งานได้ คุณสามารถใช้ข้อมูลนี้เพื่อแสดงรายชื่อเพื่อนที่ออนไลน์และแชทได้ฟรี หรือจัดเรียงอุปกรณ์ IoT ตาม "เห็นครั้งสุดท้าย"

Cloud Firestore ไม่ได้รองรับการตรวจหาบุคคลโดยค่าเริ่มต้น แต่คุณสามารถใช้ประโยชน์จากผลิตภัณฑ์อื่นๆ ของ Firebase เพื่อสร้างระบบการตรวจหาบุคคลในบ้านได้

โซลูชัน: Cloud Functions ที่มี Realtime Database

หากต้องการเชื่อมต่อ Cloud Firestore กับฟีเจอร์การแสดงสถานะแบบเนทีฟของ Firebase Realtime Database ให้ใช้ Cloud Functions

ใช้ Realtime Database เพื่อรายงานสถานะการเชื่อมต่อ จากนั้นใช้ Cloud Functions เพื่อมิเรอร์ข้อมูลดังกล่าวไปยัง Cloud Firestore

การใช้การแสดงตัวในฐานข้อมูลเรียลไทม์

ก่อนอื่นให้พิจารณาวิธีการทำงานของระบบการตรวจหาบุคคลในบ้านแบบดั้งเดิมใน Realtime Database

เว็บไซต์

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

ตัวอย่างนี้เป็นระบบการแสดงตัวตนของ Realtime Database ที่สมบูรณ์ รองรับการยกเลิกการเชื่อมต่อ ข้อขัดข้อง และอื่นๆ

กำลังเชื่อมต่อกับ Cloud Firestore

หากต้องการใช้โซลูชันที่คล้ายกันใน Cloud Firestore ให้ใช้โค้ด Realtime Database เดียวกัน จากนั้นใช้ Cloud Functions เพื่อทำให้ Realtime Database และ Cloud Firestore ซิงค์กัน

เพิ่ม Realtime Database ลงในโปรเจ็กต์และระบุโซลูชันการแสดงข้อมูลผลิตภัณฑ์ในด้านบน หากยังไม่ได้ดำเนินการ

จากนั้นคุณจะซิงค์สถานะการแสดงข้อมูลกับ Cloud Firestore ด้วยวิธีต่อไปนี้

  1. ในเครื่อง ไปยังแคช Cloud Firestore ของอุปกรณ์ที่ออฟไลน์อยู่ เพื่อให้แอปทราบว่าออฟไลน์อยู่
  2. ทั่วโลกโดยใช้ Cloud Function เพื่อให้อุปกรณ์อื่นๆ ทั้งหมดที่เข้าถึง Cloud Firestore ทราบว่าอุปกรณ์นี้ออฟไลน์อยู่

กำลังอัปเดตแคชในเครื่องของ Cloud Firestore

ลองมาดูการเปลี่ยนแปลงที่จำเป็นเพื่อให้ปัญหาแรกเสร็จสมบูรณ์ นั่นคือการอัปเดตแคชในเครื่องของ Cloud Firestore

เว็บไซต์

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

การเปลี่ยนแปลงเหล่านี้ทำให้มั่นใจได้ว่าสถานะ Cloud Firestore ในเครื่องจะแสดงสถานะออนไลน์/ออฟไลน์ของอุปกรณ์เสมอ ซึ่งหมายความว่าคุณจะฟังเอกสาร /status/{uid} และใช้ข้อมูลเพื่อเปลี่ยน UI ให้แสดงสถานะการเชื่อมต่อได้

เว็บไซต์

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

กำลังอัปเดต Cloud Firestore ทั่วโลก

แม้ว่าแอปพลิเคชันของเราจะรายงานตัวตนบนโลกออนไลน์ได้อย่างถูกต้อง แต่สถานะนี้จะยังไม่ถูกต้องในแอป Cloud Firestore อื่นๆ เนื่องจากการเขียนสถานะ "ออฟไลน์" เป็นแบบภายในเท่านั้นและจะไม่ซิงค์เมื่อคืนค่าการเชื่อมต่อ โดยเราจะใช้ Cloud Function เพื่อดูเส้นทาง status/{uid} ในฐานข้อมูลแบบเรียลไทม์เพื่อรับมือกับปัญหานี้ เมื่อค่า Realtime Database เปลี่ยนแปลง ค่าจะซิงค์กับ Cloud Firestore เพื่อให้สถานะของผู้ใช้ทั้งหมดถูกต้อง

Node.js

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

เมื่อทำให้ฟังก์ชันนี้ใช้งานได้แล้ว คุณจะมีระบบการตรวจหาบุคคลที่สมบูรณ์ที่ทำงานด้วย Cloud Firestore ด้านล่างนี้เป็นตัวอย่างการตรวจสอบผู้ใช้ที่ออนไลน์หรือออฟไลน์โดยใช้คำค้นหา where()

เว็บไซต์

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

ข้อจำกัด

การใช้ Realtime Database เพื่อเพิ่มการแสดงข้อมูลในแอป Cloud Firestore สามารถปรับขนาดได้และมีประสิทธิภาพ แต่มีข้อจำกัดบางประการดังนี้

  • การดีเบานซ์ - เมื่อฟังการเปลี่ยนแปลงแบบเรียลไทม์ใน Cloud Firestore โซลูชันนี้มีแนวโน้มที่จะทำให้เกิดการเปลี่ยนแปลงหลายรายการ หากการเปลี่ยนแปลงเหล่านี้ทริกเกอร์เหตุการณ์มากกว่าที่คุณต้องการ ให้ดีปล้นเหตุการณ์ Cloud Firestore ด้วยตนเอง
  • การเชื่อมต่อ - การติดตั้งใช้งานนี้วัดการเชื่อมต่อกับฐานข้อมูลแบบเรียลไทม์ ไม่ใช่ Cloud Firestore หากสถานะการเชื่อมต่อกับฐานข้อมูลแต่ละรายการไม่เหมือนกัน โซลูชันนี้อาจรายงานสถานะการตรวจหาบุคคลที่ไม่ถูกต้อง
  • Android - บน Android ฐานข้อมูลเรียลไทม์จะตัดการเชื่อมต่อจากแบ็กเอนด์หลังจากไม่มีการใช้งาน 60 วินาที การไม่ใช้งานหมายถึงไม่มี Listener แบบเปิด หรือการดำเนินการที่รอดำเนินการ หากต้องการเปิดการเชื่อมต่อไว้ เราขอแนะนำให้คุณเพิ่ม Listener เหตุการณ์มูลค่าลงในเส้นทางนอกเหนือจาก .info/connected ตัวอย่างเช่น คุณจะFirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() ได้ตั้งแต่เริ่มต้นแต่ละเซสชัน ดูข้อมูลเพิ่มเติมได้ที่การตรวจหาสถานะการเชื่อมต่อ