Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

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

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

ในวงจรชีวิตทั่วไป ฟังก์ชันฐานข้อมูลเรียลไทม์ของ Firebase จะทำสิ่งต่อไปนี้:

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

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

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

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

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

  • onWrite() ซึ่งทริกเกอร์เมื่อข้อมูลถูกสร้างปรับปรุงหรือลบในฐานข้อมูลเรียลไทม์
  • onCreate() ซึ่งทริกเกอร์เมื่อมีข้อมูลใหม่ถูกสร้างขึ้นในฐานข้อมูลเรียลไทม์
  • onUpdate() ซึ่งทริกเกอร์เมื่อมีการปรับปรุงข้อมูลในฐานข้อมูลเรียลไทม์
  • onDelete() ซึ่งทริกเกอร์เมื่อข้อมูลถูกลบออกจากฐานข้อมูลเรียลไทม์

ระบุอินสแตนซ์และเส้นทาง

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

  • เริ่มต้นเช่น Realtime ฐานข้อมูล functions.database.ref('/foo/bar')
  • กรณีที่มีชื่อของฉัน "แอป-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 วัตถุที่มีสองภาพรวมที่เป็นตัวแทนของรัฐข้อมูลก่อนและหลังเหตุการณ์วิกฤติ สำหรับ 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 คุณสมบัติที่ช่วยให้คุณตรวจสอบสิ่งที่ถูกบันทึกไว้ในฐานข้อมูลเรียลไทม์ก่อนที่เหตุการณ์ 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);
    });