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

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

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

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

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

หากต้องการเชื่อมต่อ Cloud Firestore กับฟีเจอร์การปรากฏของฐานข้อมูลเรียลไทม์ของ Firebase ให้ใช้ Cloud Functions

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

การใช้สถานะใน Realtime Database

ก่อนอื่น ให้พิจารณาวิธีการทำงานของระบบการปรากฏตัวแบบดั้งเดิมใน 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 ให้ใช้โค้ดฐานข้อมูลเรียลไทม์เดียวกัน จากนั้นใช้ Cloud Functions เพื่อซิงค์ฐานข้อมูลเรียลไทม์และ Cloud Firestore อยู่เสมอ

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

ถัดไป คุณจะต้องซิงค์สถานะการปรากฏกับ Cloud Firestore ผ่านวิธีการต่อไปนี้

  1. ในเครื่อง ไปยังแคช Cloud Firestore ของอุปกรณ์ออฟไลน์เพื่อให้แอปทราบว่าอุปกรณ์ออฟไลน์อยู่
  2. ทั่วโลกโดยใช้ฟังก์ชัน Cloud เพื่อให้อุปกรณ์อื่นๆ ทั้งหมดที่เข้าถึง 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 Functions ที่คอยตรวจสอบเส้นทาง status/{uid} ในฐานข้อมูลเรียลไทม์เพื่อรับมือกับปัญหานี้ เมื่อค่าฐานข้อมูลเรียลไทม์เปลี่ยนแปลง ค่าจะซิงค์กับ 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 นั้น Realtime Database จะตัดการเชื่อมต่อจากแบ็กเอนด์หลังจากไม่มีการใช้งานเป็นเวลา 60 วินาที ไม่มีการดําเนินการหมายความว่าไม่มี Listener ที่เปิดอยู่หรือการดำเนินการที่รอดำเนินการ เราขอแนะนําให้คุณเพิ่ม Listener เหตุการณ์ที่มีค่าลงในเส้นทางอื่นนอกเหนือจาก .info/connected เพื่อให้การเชื่อมต่อเปิดอยู่ เช่น คุณอาจใช้ FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() ที่จุดเริ่มต้นของแต่ละเซสชัน โปรดดูข้อมูลเพิ่มเติมที่หัวข้อการตรวจหาสถานะการเชื่อมต่อ