Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

ทริกเกอร์ฐานข้อมูลเรียลไทม์

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

ด้วย Cloud Functions คุณสามารถจัดการเหตุการณ์ใน Firebase Realtime Database โดยไม่จำเป็นต้องอัปเดตโค้ดไคลเอ็นต์ Cloud Functions ช่วยให้คุณดำเนินการกับฐานข้อมูลเรียลไทม์ด้วยสิทธิ์การดูแลระบบเต็มรูปแบบ และรับรองว่าการเปลี่ยนแปลงแต่ละครั้งในฐานข้อมูลเรียลไทม์จะได้รับการประมวลผลทีละรายการ คุณสามารถทำการเปลี่ยนแปลง Firebase Realtime Database ผ่าน DataSnapshot หรือผ่าน Admin SDK

ในวงจรชีวิตทั่วไป ฟังก์ชัน Firebase Realtime Database ดำเนินการต่อไปนี้:

  1. รอการเปลี่ยนแปลงตำแหน่งฐานข้อมูลเรียลไทม์เฉพาะ
  2. ทริกเกอร์เมื่อมีเหตุการณ์เกิดขึ้นและดำเนินการตามงานต่างๆ (ดูตัวอย่างกรณีการใช้งาน ฉันทำอะไรได้บ้างกับ Cloud Functions )
  3. รับวัตถุข้อมูลที่มีภาพรวมของข้อมูลที่จัดเก็บไว้ในเอกสารที่ระบุ

เรียกใช้ฟังก์ชันฐานข้อมูลเรียลไทม์

สร้างฟังก์ชันใหม่สำหรับเหตุการณ์ Realtime Database ด้วย functions.database ในการควบคุมเวลาที่ทริกเกอร์ฟังก์ชัน ให้ระบุตัวจัดการเหตุการณ์หนึ่งตัว และระบุพาธฐานข้อมูลเรียลไทม์ที่จะคอยฟังเหตุการณ์

ตั้งค่าตัวจัดการเหตุการณ์

ฟังก์ชันต่างๆ ช่วยให้คุณจัดการเหตุการณ์ฐานข้อมูลเรียลไทม์ได้ในระดับความเฉพาะเจาะจงสองระดับ คุณสามารถฟังเฉพาะเหตุการณ์การสร้าง อัปเดต หรือการลบ หรือคุณสามารถฟังการเปลี่ยนแปลงใดๆ ก็ตามในเส้นทาง Cloud Functions รองรับตัวจัดการเหตุการณ์เหล่านี้สำหรับ Realtime Database:

  • onWrite() ซึ่งจะทริกเกอร์เมื่อมีการสร้าง อัปเดต หรือลบข้อมูลใน Realtime Database
  • onCreate() ซึ่งจะทริกเกอร์เมื่อมีการสร้างข้อมูลใหม่ใน Realtime Database
  • onUpdate() ซึ่งจะทริกเกอร์เมื่อมีการอัปเดตข้อมูลใน Realtime Database
  • onDelete() ซึ่งจะทริกเกอร์เมื่อข้อมูลถูกลบออกจาก Realtime Database

ระบุตัวอย่างและเส้นทาง

หากต้องการควบคุมเวลาและตำแหน่งที่ฟังก์ชันของคุณควรทริกเกอร์ ให้เรียก ref(path) เพื่อระบุพาธ และเลือกที่จะระบุอินสแตนซ์ฐานข้อมูลเรียลไทม์ด้วย instance('INSTANCE_NAME') หากคุณไม่ระบุอินสแตนซ์ ฟังก์ชันจะปรับใช้กับอินสแตนซ์ฐานข้อมูลเรียลไทม์เริ่มต้นสำหรับโปรเจ็กต์ Firebase ตัวอย่างเช่น:

  • อินสแตนซ์ฐานข้อมูลเรียลไทม์เริ่มต้น: functions.database.ref('/foo/bar')
  • อินสแตนซ์ชื่อ "my-app-db-2": functions.database.instance('my-app-db-2').ref('/foo/bar')

เมธอดเหล่านี้กำหนดให้ฟังก์ชันของคุณจัดการกับการเขียนที่เส้นทางเฉพาะภายในอินสแตนซ์ฐานข้อมูลเรียลไทม์ ข้อมูลจำเพาะของพาธตรงกับการเขียน ทั้งหมด ที่สัมผัสพาธ รวมทั้งการเขียนที่เกิดขึ้นที่ใดก็ได้ด้านล่าง หากคุณกำหนดเส้นทางสำหรับฟังก์ชันของคุณเป็น /foo/bar เส้นทางจะจับคู่เหตุการณ์ที่ตำแหน่งทั้งสองนี้:

 /foo/bar
 /foo/bar/baz/really/deep/path

ไม่ว่าในกรณีใด Firebase จะตีความว่าเหตุการณ์เกิดขึ้นที่ /foo/bar และข้อมูลเหตุการณ์รวมถึงข้อมูลเก่าและใหม่ที่ /foo/bar หากข้อมูลเหตุการณ์อาจมีขนาดใหญ่ ให้พิจารณาใช้หลายฟังก์ชันที่เส้นทางที่ลึกกว่า แทนที่จะใช้ฟังก์ชันเดียวใกล้กับรากของฐานข้อมูลของคุณ เพื่อประสิทธิภาพที่ดีที่สุด ขอข้อมูลในระดับที่ลึกที่สุดเท่านั้น

คุณสามารถระบุคอมโพเนนต์พาธเป็นไวด์การ์ดได้โดยใช้วงเล็บปีกกาล้อมรอบ ref('foo/{bar}') จับคู่ลูกของ /foo ค่าของคอมโพเนนต์เส้นทางไวด์การ์ดเหล่านี้มีอยู่ภายในอ็อบเจ็กต์ EventContext.params ของฟังก์ชันของคุณ ในตัวอย่างนี้ ค่าจะพร้อมใช้งานเป็น context.params.bar

เส้นทางที่มีสัญลักษณ์แทนสามารถจับคู่หลายเหตุการณ์จากการเขียนครั้งเดียว แทรกของ

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

จับคู่เส้นทาง "/foo/{bar}" สองครั้ง: อีกครั้งกับ "hello": "world" และอีกครั้งด้วย "firebase": "functions"

จัดการข้อมูลเหตุการณ์

เมื่อจัดการเหตุการณ์ฐานข้อมูลเรียลไทม์ อ็อบเจ็กต์ข้อมูลที่ส่งคืนคือ DataSnapshot สำหรับเหตุการณ์ onWrite หรือ onUpdate พารามิเตอร์แรกคือ Change object ที่มีสแน็ปช็อตสองภาพที่แสดงสถานะข้อมูลก่อนและหลังเหตุการณ์ทริกเกอร์ สำหรับเหตุการณ์ onCreate และ onDelete อ็อบเจ็กต์ข้อมูลที่ส่งกลับคือสแน็ปช็อตของข้อมูลที่สร้างหรือลบ

ในตัวอย่างนี้ ฟังก์ชันดึงสแน็ปช็อตสำหรับเส้นทางที่ระบุเป็น snap แปลงสตริงที่ตำแหน่งนั้นเป็นตัวพิมพ์ใหญ่ และเขียนสตริงที่แก้ไขไปยังฐานข้อมูล:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

การเข้าถึงข้อมูลการตรวจสอบผู้ใช้

จาก EventContext.auth และ EventContext.authType คุณสามารถเข้าถึงข้อมูลผู้ใช้ รวมถึงสิทธิ์สำหรับผู้ใช้ที่เรียกใช้ฟังก์ชัน สิ่งนี้มีประโยชน์สำหรับการบังคับใช้กฎความปลอดภัย ทำให้ฟังก์ชันของคุณสามารถดำเนินการต่างๆ ให้เสร็จสมบูรณ์ตามระดับสิทธิ์ของผู้ใช้:

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

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

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

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

การอ่านค่าก่อนหน้า

อ็อบเจ็กต์ Change มีคุณสมบัติ before ที่ให้คุณตรวจสอบสิ่งที่บันทึกไว้ใน Realtime Database ก่อน เหตุการณ์ คุณสมบัติ before ส่งคืน DataSnapshot โดยที่เมธอดทั้งหมด (เช่น val() และไม่ exists() ) อ้างถึงค่าก่อนหน้า คุณสามารถอ่านค่าใหม่ได้อีกครั้งโดยใช้ DataSnapshot เดิมหรืออ่านคุณสมบัติ after คุณสมบัตินี้ในการ Change ใด ๆ คือ DataSnapshot อื่นที่แสดงสถานะของข้อมูล หลังจาก เหตุการณ์เกิดขึ้น

ตัวอย่างเช่น สามารถใช้คุณสมบัติ before เพื่อให้แน่ใจว่าฟังก์ชันจะพิมพ์ข้อความตัวพิมพ์ใหญ่เท่านั้นเมื่อสร้างครั้งแรก:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return change.after.ref.parent.child('uppercase').set(uppercase);
    });