Skip to content

Firestore – Batch & Transaction

Với những ai đã từng sử dụng MySQL, SQL Server thì đều biết những database này đều hỗ trợ cơ chế Transaction. Còn batch, nếu bạn đã biết về Java JDBC thì sẽ biết về batch

Batch là khi bạn muốn write một loạt những action vào database nhưng muốn những action đó luôn luôn được đảm bảo là thành công ! Nếu một action thất bại => Tất cả action khác bị cancel

Transaction thì liên quan đến vấn đều nâng cao hơn là tránh Race Condition (dữ liệu bị ghi đè)

Bài viết này không nói rõ về Transaction là gì nhưng chỉ nó về ~ khái niệm này trong Firestore

Đối với Firestore, về mặt ý nghĩa thì đều giống như cổ điển nhưng cách thức vận hành thì khác. Transaction không ROLL_BACK mà luôn luôn thành công

Cùng tìm hiểu thêm ở phía dưới nào :))


Table of Contents

    Mỗi Transaction hay Batch : Limit : Write => 500 documents

    Batch Write

    Update toàn bộ 1 lượt trên nhiều Document mà không bị Breakout

    Sử dụng cho : Write(Create, Update, Delete)

    Cú pháp : set()update(), or delete()

    var batch = db.batch();
    
    var nycRef = db.collection("cities").doc("NYC");
    batch.set(nycRef, {name: "New York City"});
    
    var sfRef = db.collection("cities").doc("SF");
    batch.update(sfRef, {"population": 1000000});
    
    var laRef = db.collection("cities").doc("LA");
    batch.delete(laRef);
    
    batch.commit().then(function () {
        // ...
    });
    

    Limit : 20 actions / Batch

    Data Validation

    match /cities/{city} {
      allow write: if request.auth != null &&
      getAfter(
    /databases/$(database)/documents/countries/$(request.resource.data.country)
    )
         .data.last_updated == request.time;
    }
    service cloud.firestore {
        match /databases/{db}/documents {
          function prefix() {
            return /databases/{db}/documents;
          }
          match /chatroom/{roomId} {
            allow read, write: if request.auth != null && roomId in get(/$(prefix())/users/$(request.auth.uid)).data.chats
                                  || exists(/$(prefix())/admins/$(request.auth.uid));
          }
          match /users/{userId} {
            allow read, write: if request.auth != null && request.auth.uid == userId
                                  || exists(/$(prefix())/admins/$(request.auth.uid));
          }
          match /admins/{userId} {
            allow read, write: if request.auth != null && exists(/$(prefix())/admins/$(request.auth.uid));
          }
        }
    }

    Transaction

    Cách thức hoạt động

    Chính vì luôn luôn double-check trước khi thực hiện action => Không cần phải roll-back. Cứ mỗi lần check mà thấy sai => Chạy lại từ đầu

    Gồm : set()update(), or delete()

    var sfDocRef = db.collection("cities").doc("SF");
    
    // sfDocRef.set({ population: 0 });
    
    return db.runTransaction(function(transaction) {
        return transaction.get(sfDocRef).then(function(sfDoc) {
            if (!sfDoc.exists) {
                throw "Document does not exist!";
            }
    
           
            var newPopulation = sfDoc.data().population + 1;
            transaction.update(sfDocRef, { population: newPopulation });
        });
    }).then(() => {   }).catch(() => {
       });
    

    // Note: this could be done without a transaction
    // by updating the population using FieldValue.increment()

    Lưu ý : Đừng thay đổi application state bên trong transaction function. Vì lý do Transaction sẽ chạy lại ! => Không đảm bảo

    Published inFirestore

    Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *