ทริกเกอร์ Cloud Firestore (รุ่นที่ 1)

Cloud Functions ช่วยให้คุณจัดการเหตุการณ์ใน Cloud Firestore ได้โดยไม่ต้องอัปเดตโค้ดฝั่งไคลเอ็นต์ คุณทำการเปลี่ยนแปลง Cloud Firestore ได้ผ่าน อินเทอร์เฟซสแนปชอตของเอกสารหรือผ่าน Admin SDK

ในวงจรการใช้งานทั่วไป ฟังก์ชัน Cloud Firestore จะทำสิ่งต่อไปนี้

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

ระยะห่างระหว่างตำแหน่งของอินสแตนซ์ Firestore กับตำแหน่งของฟังก์ชันอาจทำให้เกิดเวลาในการตอบสนองของเครือข่ายที่มาก หากต้องการเพิ่มประสิทธิภาพ ให้ระบุตำแหน่งฟังก์ชันเมื่อ เป็นไปได้

ทริกเกอร์ฟังก์ชัน Cloud Firestore

Cloud Functions for Firebase SDK จะส่งออกออบเจ็กต์ functions.firestore ซึ่งช่วยให้คุณสร้างตัวแฮนเดิลที่เชื่อมโยงกับเหตุการณ์ Cloud Firestore ที่เฉพาะเจาะจงได้

ประเภทเหตุการณ์ ทริกเกอร์
onCreate ทริกเกอร์เมื่อมีการเขียนเอกสารเป็นครั้งแรก
onUpdate ทริกเกอร์เมื่อมีเอกสารอยู่แล้วและมีการเปลี่ยนแปลงค่า
onDelete ทริกเกอร์เมื่อมีการลบเอกสารที่มีข้อมูล
onWrite ทริกเกอร์เมื่อมีการทริกเกอร์ onCreate, onUpdate หรือ onDelete

หากยังไม่ได้เปิดใช้โปรเจ็กต์สำหรับ Cloud Functions for Firebase ให้อ่าน เริ่มต้นใช้งาน: เขียนและติดตั้งใช้งานฟังก์ชันแรก เพื่อกำหนดค่าและตั้งค่าโปรเจ็กต์ Cloud Functions for Firebase

การเขียนฟังก์ชันที่ทริกเกอร์โดย Cloud Firestore

กำหนดทริกเกอร์ฟังก์ชัน

หากต้องการกำหนดทริกเกอร์ Cloud Firestore ให้ระบุเส้นทางเอกสารและประเภทเหตุการณ์

Node.js

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

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

เส้นทางเอกสารสามารถอ้างอิงเอกสารที่เฉพาะเจาะจง หรือรูปแบบไวลด์การ์ดก็ได้

ระบุเอกสารเดียว

หากต้องการทริกเกอร์เหตุการณ์เมื่อมีการเปลี่ยนแปลงใดๆ ในเอกสารที่เฉพาะเจาะจง ให้ใช้ฟังก์ชันต่อไปนี้

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((change, context) => {
      // ... Your code here
    });

ระบุกลุ่มเอกสารโดยใช้ไวลด์การ์ด

หากต้องการแนบทริกเกอร์กับกลุ่มเอกสาร เช่น เอกสารใดก็ตามในคอลเล็กชันหนึ่ง ให้ใช้ {wildcard} แทนรหัสเอกสาร

Node.js

// Listen for changes in all documents in the 'users' collection
exports.useWildcard = functions.firestore
    .document('users/{userId}')
    .onWrite((change, context) => {
      // If we set `/users/marie` to {name: "Marie"} then
      // context.params.userId == "marie"
      // ... and ...
      // change.after.data() == {name: "Marie"}
    });

ในตัวอย่างนี้ เมื่อมีการเปลี่ยนแปลงฟิลด์ใดก็ตามในเอกสารใดก็ตามใน users ระบบจะจับคู่กับ อักขระไวด์การ์ดที่ชื่อ userId

หากเอกสารใน users มีคอลเล็กชันย่อย และมีการเปลี่ยนแปลงฟิลด์ในเอกสารของคอลเล็กชันย่อยเหล่านั้น userId ไวลด์การ์ดจะไม่ทริกเกอร์

ระบบจะดึงข้อมูลการจับคู่ไวลด์การ์ดจากเส้นทางของเอกสารและจัดเก็บไว้ใน context.params คุณกำหนดสัญลักษณ์แทนได้มากเท่าที่ต้องการเพื่อแทนที่คอลเล็กชันหรือรหัสเอกสารที่ชัดเจน เช่น

Node.js

// Listen for changes in all documents in the 'users' collection and all subcollections
exports.useMultipleWildcards = functions.firestore
    .document('users/{userId}/{messageCollectionId}/{messageId}')
    .onWrite((change, context) => {
      // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
      // context.params.userId == "marie";
      // context.params.messageCollectionId == "incoming_messages";
      // context.params.messageId == "134";
      // ... and ...
      // change.after.data() == {body: "Hello"}
    });

ทริกเกอร์เหตุการณ์

เรียกใช้ฟังก์ชันเมื่อมีการสร้างเอกสารใหม่

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

Node.js

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = snap.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

เรียกใช้ฟังก์ชันเมื่อมีการอัปเดตเอกสาร

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

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

เรียกใช้ฟังก์ชันเมื่อมีการลบเอกสาร

นอกจากนี้ คุณยังทริกเกอร์ฟังก์ชันเมื่อมีการลบเอกสารได้โดยใช้ฟังก์ชัน onDelete() ที่มีไวลด์การ์ด ตัวอย่างนี้ ฟังก์ชันจะเรียกใช้ deleteUser เมื่อผู้ใช้ลบโปรไฟล์ผู้ใช้ของตนเอง

Node.js

exports.deleteUser = functions.firestore
    .document('users/{userID}')
    .onDelete((snap, context) => {
      // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();

      // perform desired operations ...
    });

ทริกเกอร์ฟังก์ชันสำหรับการเปลี่ยนแปลงทั้งหมดในเอกสาร

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

Node.js

exports.modifyUser = functions.firestore
    .document('users/{userID}')
    .onWrite((change, context) => {
      // Get an object with the current document value.
      // If the document does not exist, it has been deleted.
      const document = change.after.exists ? change.after.data() : null;

      // Get an object with the previous document value (for update or delete)
      const oldDocument = change.before.data();

      // perform desired operations ...
    });

การอ่านและการเขียนข้อมูล

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

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

ข้อมูลการอ่าน

เมื่อฟังก์ชันทริกเกอร์ คุณอาจต้องการรับข้อมูลจากเอกสารที่ อัปเดตแล้ว หรือรับข้อมูลก่อนการอัปเดต คุณดูข้อมูลก่อนหน้าได้โดยใช้ change.before.data() ซึ่งมีสแนปชอตของเอกสารก่อนการอัปเดต ในทำนองเดียวกัน change.after.data() จะมีสถานะสแนปชอตของเอกสารหลังจากอัปเดต

Node.js

exports.updateUser2 = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the current document
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();
    });

คุณเข้าถึงพร็อพเพอร์ตี้ได้เช่นเดียวกับในออบเจ็กต์อื่นๆ หรือคุณจะใช้ฟังก์ชัน get เพื่อเข้าถึงฟิลด์ที่เฉพาะเจาะจงก็ได้

Node.js

// Fetch data using standard accessors
const age = snap.data().age;
const name = snap.data()['name'];

// Fetch data using built in accessor
const experience = snap.get('experience');

การเขียนข้อมูล

การเรียกใช้ฟังก์ชันแต่ละครั้งจะเชื่อมโยงกับเอกสารที่เฉพาะเจาะจงในฐานข้อมูล Cloud Firestore คุณเข้าถึงเอกสารนั้นได้ในฐานะ DocumentReference ในพร็อพเพอร์ตี้ ref ของสแนปชอตที่ส่งคืนไปยังฟังก์ชัน

DocumentReference นี้มาจาก Cloud Firestore Node.js SDK และมีเมธอดต่างๆ เช่น update(), set() และ remove() เพื่อให้คุณแก้ไขเอกสารที่ทริกเกอร์ฟังก์ชันได้อย่างง่ายดาย

Node.js

// Listen for updates to any `user` document.
exports.countNameChanges = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Retrieve the current and previous value
      const data = change.after.data();
      const previousData = change.before.data();

      // We'll only update if the name has changed.
      // This is crucial to prevent infinite loops.
      if (data.name == previousData.name) {
        return null;
      }

      // Retrieve the current count of name changes
      let count = data.name_change_count;
      if (!count) {
        count = 0;
      }

      // Then return a promise of a set operation to update the count
      return change.after.ref.set({
        name_change_count: count + 1
      }, {merge: true});
    });

ข้อมูลนอกเหตุการณ์ทริกเกอร์

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

Node.js

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

const db = admin.firestore();

exports.writeToFirestore = functions.firestore
  .document('some/doc')
  .onWrite((change, context) => {
    db.doc('some/otherdoc').set({ ... });
  });

ข้อจำกัด

โปรดทราบข้อจำกัดต่อไปนี้สำหรับทริกเกอร์ Cloud Firestore สำหรับ Cloud Functions

  • Cloud Functions (รุ่นที่ 1) ต้องมีฐานข้อมูล "(default)" ในโหมดเนทีฟของ Firestore อยู่แล้ว แต่ไม่รองรับCloud Firestoreฐานข้อมูลที่มีชื่อหรือโหมด Datastore โปรดใช้ Cloud Functions (รุ่นที่ 2) เพื่อกำหนดค่าเหตุการณ์ในกรณีดังกล่าว
  • ไม่มีการรับประกันการสั่งซื้อ การเปลี่ยนแปลงอย่างรวดเร็วอาจทริกเกอร์การเรียกใช้ฟังก์ชันในลำดับที่ไม่คาดคิด
  • ระบบจะส่งเหตุการณ์อย่างน้อย 1 ครั้ง แต่เหตุการณ์เดียวอาจทำให้เกิดการเรียกใช้ฟังก์ชันหลายครั้ง หลีกเลี่ยงการใช้กลไกการทำงานแบบส่งครั้งเดียวที่แน่นอน และเขียนฟังก์ชันที่ไม่มีผลข้างเคียง
  • Cloud Firestore ในโหมด Datastore ต้องใช้ Cloud Functions (รุ่นที่ 2) Cloud Functions (รุ่นที่ 1) ไม่รองรับโหมด Datastore
  • ทริกเกอร์จะเชื่อมโยงกับฐานข้อมูลเดียว คุณสร้างทริกเกอร์ที่ตรงกับฐานข้อมูลหลายรายการไม่ได้
  • การลบฐานข้อมูลจะไม่ลบทริกเกอร์สำหรับฐานข้อมูลนั้นโดยอัตโนมัติ ทริกเกอร์จะหยุดส่งกิจกรรม แต่จะยังคงอยู่จนกว่าคุณจะลบทริกเกอร์
  • หากเหตุการณ์ที่ตรงกันมีขนาดเกินขนาดคำขอสูงสุด ระบบอาจไม่ส่งเหตุการณ์ไปยัง Cloud Functions (รุ่นที่ 1)
    • ระบบจะบันทึกเหตุการณ์ที่นำส่งไม่ได้เนื่องจากขนาดคำขอในบันทึกของแพลตฟอร์ม และนับรวมในการใช้งานบันทึกของโปรเจ็กต์
    • คุณดูบันทึกเหล่านี้ได้ในตัวสำรวจบันทึกโดยมีข้อความ "ส่งเหตุการณ์ไปยังฟังก์ชัน Cloud ไม่ได้เนื่องจากขนาดเกินขีดจำกัดสำหรับรุ่นที่ 1..." ของerror ระดับความรุนแรง คุณจะเห็นชื่อฟังก์ชันในช่อง functionName หากฟิลด์ receiveTimestamp ยังอยู่ภายใน 1 ชั่วโมงนับจากนี้ คุณจะอนุมาน เนื้อหาเหตุการณ์จริงได้โดยอ่านเอกสารที่เป็นปัญหาพร้อม สแนปชอตก่อนและหลังการประทับเวลา
    • หากต้องการหลีกเลี่ยงการส่งอีเมลตามช่วงเวลาดังกล่าว ให้ทำดังนี้
      • ย้ายข้อมูลและอัปเกรดเป็น Cloud Functions (รุ่นที่ 2)
      • ลดขนาดเอกสาร
      • ลบ Cloud Functions ที่มีปัญหา
    • คุณปิดการบันทึกได้โดยใช้การยกเว้น แต่โปรดทราบว่าระบบจะไม่ส่งเหตุการณ์ที่เป็นปัญหา