【问题标题】:firebase RTDB transactional deletefirebase RTDB 事务删除
【发布时间】:2020-11-24 18:55:05
【问题描述】:

我一直在很好地使用 Firestore 事务,并且一直在尝试实现一些 RTDB 版本。

我有一棵带有自动生成键的树。这些键的值是映射,其中一个键是“uid”,例如

"AUTOGENKEY" : {
    "uid" : 'a uid'
}, 
...etc

我想要一个可以删除所有单身用户节点的事务...如果用户在事务期间创建了任何新节点,它应该重试并将新节点包含在事务删除中。

我现在有这个


await rtdb.ref(‘someRef’)
    .orderByChild(‘uid’)
    .equalTo(uid)
    .once('value')
    .transaction(function(currentVal) {
            // Loop each of the nodes with a matching ‘uid’ and delete them
            // If any of the nodes are updated (or additional nodes are created with matching uids)
           // while the transaction is running it should restart and retry the delete        
           // If no nodes are matched nothing should happen    
    });

但我想仔细检查一下我是否需要在 currentVal 回调中进行另一个事务,以及我是否可以只返回 null 来删除每个节点。

我一直使用这个答案作为参考Firebase database transactional search and update

亲切的问候

-编辑新方法

我坦率地接受了你的建议,最终只是像这样存储我的数据:

uid -> counter 

我不知道事务不能在查询上运行,感谢您告诉我。

我需要能够从 uids 计数中添加/减去数量,如果它导致数字低于 0,则应删除该节点。如果我将 null 作为数量传递,它应该删除节点。这是我目前拥有的。

async function incrementOrDecrementByAmount(pathToUid, shouldAdd, amount, rtdb){

  await rtdb.ref(pathToUid)
    .transaction(function(currentVal) {
   
      if(currentVal == null || amount == null) {
        return amount;
      }else{
        let newAmount = null;

        // Just sum the new amount
        if(shouldAdd == true) {
          newAmount = currentVal + amount;
        } else {
          const diff = currentVal - amount;

          // If its not above 0 then leave it null so it is deleted
          if(newAmount > 0) {
            newAmount = diff;
          }
        }

        return newAmount;
      }
    });
}


如果我有以下执行,我不确定第一个 if 语句。

  1. incrementOrDecrementByAmount(somePath, 10, true, rtdb)
  2. incrementOrDecrementByAmount(somePath, 100, false, rtdb)

这是否总是会导致节点被删除?事务是始终依赖于调用顺序还是谁先完成的竞争条件。

【问题讨论】:

    标签: javascript firebase firebase-realtime-database


    【解决方案1】:

    事务只能在DatabaseReference 上运行,而不能在Query 上运行。因此,在您的情况下,您必须在完整的 someRef 节点上运行事务,然后修改 currentVal 以删除 uid 属性与您的条件匹配的节点。

    如果有许多uid 值,这可能会导致读取的数据明显多于所需数据,并且如果多个用户可能同时执行此操作,则可能会导致争用和重试。在这种情况下,请考虑另一种数据结构,它允许您运行更加独立的事务,例如通过将每个 uid 值的节点存储在该值下作为键。

    someRef: {
      "uid1": {
        ...
      },
      "uid2": {
        ...
      }
    }
    

    使用这种结构,可以通过简单的单次写入操作来删除单个uid 的所有值。

    【讨论】:

    • 嗨弗兰克。感谢您的反馈。我改变了我的数据库结构并编写了一个新方法。请检查我是否正确完成了交易
    • 您需要将return newAmount 向上移动两行,到前面的}。但除此之外,它乍一看还不错。注意:我会亲自合并 shouldAdd, amount 参数,并将正数或负数传递给函数。
    • 当然不接受你的回答!由于评论// If its not above 0 then leave it null so it is deleted 中的原因,我将行留在了底部...谢谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多