从多个位置删除相同的值 Firebase 函数

Jaq*_*ine 4 javascript node.js firebase firebase-realtime-database google-cloud-functions

我有一个 firebase 功能,可以在 24 小时后删除旧消息,就像我的旧问题一样 在这里的。我现在只将 messageIds 存储在用户下的数组中,路径是:/User/objectId/myMessages,然后是 myMessages 下所有 messageIds 的数组。所有消息都会在 24 小时后删除,但用户个人资料下的 ID 会保留在那里。有没有办法继续该功能,以便它也从用户帐户下的数组中删除 messageIds?

我是 Firebase 函数和 javascript 的新手,所以我不知道该怎么做。感谢所有帮助!

sam*_*man 5

建立在@frank-van-puffelen对旧问题的接受答案的基础上,这将作为相同原子删除操作的一部分从其发件人的用户数据中删除消息 ID,而不为每条删除的消息触发云函数。

方法一:重构并发

在能够使用此方法之前,您必须重构存储条目的方式/User/someUserId/myMessages以遵循并发数组的最佳实践,如下所示:

{
  "/User/someUserId/myMessages": {
    "-Lfq460_5tm6x7dchhOn": true,
    "-Lfq483gGzmpB_Jt6Wg5": true,
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

这允许您将之前的函数修改为:

// Cut off time. Child nodes older than this will be deleted.
const CUT_OFF_TIME = 24 * 60 * 60 * 1000; // 2 Hours in milliseconds.

exports.deleteOldMessages = functions.database.ref('/Message/{chatRoomId}').onWrite(async (change) => {
    const rootRef = admin.database().ref(); // needed top level reference for multi-path update
    const now = Date.now();
    const cutoff = (now - CUT_OFF_TIME) / 1000; // convert to seconds
    const oldItemsQuery = ref.orderByChild('seconds').endAt(cutoff);
    const snapshot = await oldItemsQuery.once('value');
    // create a map with all children that need to be removed
    const updates = {};
    snapshot.forEach(messageSnapshot => {
        let senderId = messageSnapshot.child('senderId').val();
        updates['Message/' + messageSnapshot.key] = null; // to delete message
        updates['User/' + senderId + '/myMessages/' + messageSnapshot.key] = null; // to delete entry in user data
    });
    // execute all updates in one go and return the result to end the function
    return rootRef.update(updates);
});
Run Code Online (Sandbox Code Playgroud)

方法二:使用数组

警告:此方法会成为并发问题的牺牲品。如果用户在删除操作期间发布新消息,则可以在评估删除时删除它的 ID。尽可能使用方法 1 来避免这种情况。

此方法假定您的/User/someUserId/myMessages对象如下所示(一个普通数组):

{
  "/User/someUserId/myMessages": {
    "0": "-Lfq460_5tm6x7dchhOn",
    "1": "-Lfq483gGzmpB_Jt6Wg5",
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以为这个数据结构提出的最精简、最具成本效益的防冲突功能如下:

// Cut off time. Child nodes older than this will be deleted.
const CUT_OFF_TIME = 24 * 60 * 60 * 1000; // 2 Hours in milliseconds.

exports.deleteOldMessages = functions.database.ref('/Message/{chatRoomId}').onWrite(async (change) => {
    const rootRef = admin.database().ref(); // needed top level reference for multi-path update
    const now = Date.now();
    const cutoff = (now - CUT_OFF_TIME) / 1000; // convert to seconds
    const oldItemsQuery = ref.orderByChild('seconds').endAt(cutoff);
    const snapshot = await oldItemsQuery.once('value');
    // create a map with all children that need to be removed
    const updates = {};
    const messagesByUser = {};
    snapshot.forEach(messageSnapshot => {
        updates['Message/' + messageSnapshot.key] = null; // to delete message

        // cache message IDs by user for next step
        let senderId = messageSnapshot.child('senderId').val();
        if (!messagesByUser[senderId]) { messagesByUser[senderId] = []; }
        messagesByUser[senderId].push(messageSnapshot.key);
    });

    // Get each user's list of message IDs and remove those that were deleted.
    let pendingOperations = [];
    for (let [senderId, messageIdsToRemove] of Object.entries(messagesByUser)) {
        pendingOperations.push(admin.database.ref('User/' + senderId + '/myMessages').once('value')
            .then((messageArraySnapshot) => {
                let messageIds = messageArraySnapshot.val();
                messageIds.filter((id) => !messageIdsToRemove.includes(id));
                updates['User/' + senderId + '/myMessages'] = messageIds; // to update array with non-deleted values
            }));
    }
    // wait for each user's new /myMessages value to be added to the pending updates
    await Promise.all(pendingOperations);

    // execute all updates in one go and return the result to end the function
    return ref.update(updates);
});
Run Code Online (Sandbox Code Playgroud)