【问题标题】:How to delete all but most recent X children in a Firebase node?如何删除 Firebase 节点中除最近的 X 子节点之外的所有子节点?
【发布时间】:2015-11-24 07:27:11
【问题描述】:

假设一个 Firebase 节点 lines 填充了唯一 ID 子节点(来自 push() 操作),例如:

Firebase--
  --lines
    --K3qx02jslkdjNskjwLDK
    --K3qx23jakjdz9Nlskjja
    --K3qxRdXhUFmEJdifOdaj
    --etc...

我希望能够删除lines 的所有子代除了最近添加的 200 个(或 100 个,或其他)。基本上这是一个清理操作。现在我知道我可以通过在客户端获取lines 的所有子项的快照,计算条目,然后使用endsAt(totalChildren-numToKeep) 获取相关数据并运行remove() 来做到这一点。但我想避免将所有数据抓取到客户端。

我上面的想法有替代方案吗?

【问题讨论】:

    标签: firebase


    【解决方案1】:

    保留最近的 N 项,是实现起来比较棘手的用例之一。如果您有任何选项可以将其更改为“保留过去 N 小时的项目”,我建议您走这条路线。

    用例棘手的原因是您正在计算项目,而 Firebase 确实(故意)没有任何基于计数的操作。因此,您需要检索前 N 个项目才能知道哪个项目是 N+1。

    ref.child('lines').once('value', function(snapshot) {
      if (snapshot.numChildren() > MAX_COUNT) {
        var childCount = 0;
        var updates = {};
        snapshot.forEach(function (child) {
          if (++childCount < snapshot.numChildren() - MAX_COUNT) {
            updates[child.key()] = null;
          }
        });
        ref.child('lines').update(updates);
      }
    });
    

    这里有几点需要注意:

    • 这将下载所有行
    • 它执行单个 update() 调用以删除无关的行

    优化这一点的一种方法(除了选择不同的/基于时间的截断策略)是保留一个单独的“行 ID”列表。

    lineids
      --K3qx02jslkdjNskjwLDK
      --K3qx23jakjdz9Nlskjja
      --K3qxRdXhUFmEJdifOdaj
    

    因此,您仍将在lines 中保留每一行的数据,但保留仅包含 id 的列表。然后删除多余的代码变成:

    ref.child('lineids').once('value', function(snapshot) {
      if (snapshot.numChildren() > MAX_COUNT) {
        var childCount = 0;
        var updates = {};
        snapshot.forEach(function (child) {
          if (++childCount < snapshot.numChildren() - MAX_COUNT) {
            updates['lineids/'+child.key()] = null;
            updates['lines/'+child.key()] = null;
          }
        });
        ref.update(updates);
      }
    });
    

    最后一个 sn-p 稍微复杂一些,但无需通过仅下载线路 ID 来下载所有线路数据。

    您可以选择许多变体,但我希望这足以成为入门的灵感。

    【讨论】: