Firebase Cloud功能会在onUpdate上触发两次

Gur*_*Rao 5 android firebase firebase-realtime-database google-cloud-functions

我有以下规则为我 firebase collection - payments

"payments": {
    "$paymentId": {
        "totalAmount": {
        },
        "balanceAmount": {
            ".validate": "newData.val()<=data.child('totalAmount').val()"
        },
        "paymentDetails": {
            "$detailId": {
                "amount": {
                    ".validate": "newData.isString()"
                },
            }
        },
    }
}
Run Code Online (Sandbox Code Playgroud)

以及为处理该集合上的某些更新而编写的云函数:

exports.calculateBalance = functions.database
.ref('payments/{pushId}')
.onUpdate(event => {
    const paymentRef = event.data.adminRef;
    const payment = event.data.val();
    return paymentRef.once('value').then(snapshot => {
        var paidAmount = 0;
        snapshot.child("paymentDetails").forEach(function(child) {
            paidAmount += parseFloat(child.child("amount").val());
        });
        return paidAmount;
    }).then(snap => {
        payment.balanceAmount = parseFloat(payment.totalAmount) - snap;
        return paymentRef.set(payment);
    })
});
Run Code Online (Sandbox Code Playgroud)

它很简单,每当我添加付款细节时,我都想更新balanceAmount.这里的问题是,只要在该集合中发生更新,该函数就会触发两次.第一次从应用中明显看出它第二次因为paymentRef.set(payment);线路.

有没有办法可以避免云功能的第二次触发?我不能在collection级别上使用任何标志,因为付款细节的更新多次发生.有人能引导我朝着正确的方向前进吗?

编辑

注意 - 我输入了付款详细信息的编辑选项.

Pip*_*iks 4

如果您只想在添加付款详细信息时更新余额金额,您可以直接在付款详细信息上使用onCreate触发器。

尝试类似的方法(您必须更新您的案例的代码):

exports.calculateBalance = functions.database.ref('payments/{pushId}/paymentDetails/{detailId}').onCreate(event => {
    var paymentRef = event.data.adminRef.parent.parent;
    var paymentDetailSnapshot = event.data;
    var paymentDetailAmountSnapshot = paymentDetailSnapshot.child('amount');

    return paymentRef.child('balanceAmount').transaction(current => {
        return current - paymentDetailAmountSnapshot.val(); // Balance can be negative
    });
});
Run Code Online (Sandbox Code Playgroud)

(使用事务来管理并发修改)

交易文件。

笔记

请直接使用Number作为您的金额数据,而不是String

更新

添加此功能来管理更新:

exports.recalculateBalance = functions.database.ref('payments/{pushId}/paymentDetails/{detailId}').onUpdate(event => {
    var paymentRef = event.data.adminRef.parent.parent;

    var paymentDetailSnapshot = event.data;
    var previousPaymentDetailSnapshot = event.data.previous;

    var paymentDetailAmountSnapshot = paymentDetailSnapshot.child('amount');
    var previousPaymentDetailAmountSnapshot = previousPaymentDetailSnapshot.child('amount');

    return paymentRef.child('balanceAmount').transaction(current => {
        return current + previousPaymentDetailAmountSnapshot.val() - paymentDetailAmountSnapshot.val(); // Balance can be negative
    });
});
Run Code Online (Sandbox Code Playgroud)