如何解决云功能中的Firestore批量限制

时间:2019-11-12 09:33:59

标签: node.js firebase google-cloud-firestore google-cloud-functions

我正在尝试使用云功能从Firestore删除整个用户记录,但是遇到下一个错误

  

INVALID_ARGUMENT:每个请求最多允许500次写入

如何解决此问题?

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

exports.deleteUserContacts = functions
    .runWith({
        timeoutSeconds: 540,
        memory: '2GB'
    })
    .https.onCall((data,context) => {

    // ...

    return admin.firestore().collection('contacts').where('uid','==',context.auth.uid).get()
        .then(snap => {

            if (snap.size === 0) {
                console.log(`User ${context.auth.uid} has no contacts to delete`);
                return 'user has no contacts to delete';
            }

            let batch = admin.firestore().batch();

            snap.forEach(doc => {
                batch.delete(doc.ref)
            });

            return batch.commit(); //INVALID_ARGUMENT: maximum 500 writes allowed per request
        })
        .then(() => {
            console.log(`Transaction success on user ${context.auth.uid}`);
            return 'Transaction success';
        })
        .catch(error => {

            console.log(`Transaction failure on user ${context.auth.uid}`,error);
            throw new functions.https.HttpsError(
                'unknown',
                'Transaction failure'
              );
        });
});

2 个答案:

答案 0 :(得分:0)

您可能知道这是由于limit to transactions and batched writes造成的,为了规避这一限制,我发现了另一个与您有类似问题的人的帖子。

大多数建议是将其批量分配到500以下,然后再提交。

在这里,看看这里的solution

希望这会有所帮助。

答案 1 :(得分:0)

根据Stefan总结对我有用的最终解决方案。

如有任何错误,请发表评论

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

exports.deleteUserContacts = functions
    .runWith({
        timeoutSeconds: 540,
        memory: '2GB'
    })
    .https.onCall((data,context) => {

   //...

    return admin.firestore().collection('contacts').where('uid','==',context.auth.uid).get()
        .then(snap => {

            if (snap.size === 0) {
                console.log(`User ${context.auth.uid} has no contacts to delete`);
                return 'user has no contacts to delete';
            }

            const batchArray = [admin.firestore().batch()];
            let operationCounter = 0;
            let batchIndex = 0;

            snap.forEach(doc => {
                batchArray[batchIndex].delete(doc.ref);
                operationCounter++;

                if (operationCounter === 499) {
                    batchArray.push(admin.firestore().batch());
                    batchIndex++;
                    operationCounter = 0;
                }
            });

            batchArray.forEach(
                async batch => await batch.commit()
            );

            return 'function ended';
        })
        .then(() => {
            console.log(`Transaction success on user ${context.auth.uid}`);
            return 'Transaction success';
        })
        .catch(error => {

            console.log(`Transaction failure on user ${context.auth.uid}`,error);
            throw new functions.https.HttpsError(
                'unknown',
                'Transaction failure'
              );
        });
});