如何删除 Firebase 节点中除最新 X 子节点之外的所有子节点?

mix*_*mix 1 firebase

给定一个 Firebase 节点,lines其中填充了唯一 ID 子节点(来自push()操作),如下所示:

Firebase--
  --lines
    --K3qx02jslkdjNskjwLDK
    --K3qx23jakjdz9Nlskjja
    --K3qxRdXhUFmEJdifOdaj
    --etc...
Run Code Online (Sandbox Code Playgroud)

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

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

Fra*_*len 5

保留最近的 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);
  }
});
Run Code Online (Sandbox Code Playgroud)

这里有几点需要注意:

  • 这将下载所有行
  • 它执行一次update()调用来删除无关的行

优化此操作的一种方法(除了选择不同/基于时间的截断策略之外)是保留“行 id”的单独列表。

lineids
  --K3qx02jslkdjNskjwLDK
  --K3qx23jakjdz9Nlskjja
  --K3qxRdXhUFmEJdifOdaj
Run Code Online (Sandbox Code Playgroud)

因此,您仍将保留每行的数据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);
  }
});
Run Code Online (Sandbox Code Playgroud)

最后一个代码片段稍微复杂一些,但可以避免只通过下载线路 ID 来下载所有线路数据。

您可以选择多种变体,但我希望这能够为您提供足够的灵感来开始。