То есть копирование одного узла под другой

Мы находимся в середине реализации хранилища событий на нашем бэкэнде Firebase (черпая вдохновение из commanded/eventstore Бена Смита и EventStore Грега Янга), и на этом этапе необходим механизм моментальных снимков.

(Позже я нашел суть, на которую стоит обратить внимание: https://gist.github.com/katowulf/6099042)

Добавление некоторых образцов данных

После настройки Firebase и запуска Node REPL на консоли:

> const path_ref = firebase_admin.database().ref("main");
> "the cake is a lie".split(" ").forEach( function(word) { path_ref.child("topics").child(word).set({ length: word.length }) });

и правильно написать:

"the cake is a lie".split(" ").forEach(
  function(word) {
    path_ref.child("topics").child(word).set({length: word.length})
  });

Это создаст такую ​​структуру:

Создать снимок (т. е. скопировать путь под другим)

> path_ref.once("value").then(function(dataSnapshot) { path_ref.child("snapshots").push(dataSnapshot.val())});

Приведение в порядок:

path_ref.once("value").then(
  function(dataSnapshot) {
    path_ref.child("snapshots").push(dataSnapshot.val())
  });

Это приведет к следующему:

once("value") берет все содержимое path_ref (которое на данный момент /main) и возвращает Promise с DataSnapshot. Мы добавили дочерний путь моментальные снимки и добавили значение моментальных снимков данных под уникальным идентификатором (с push()).

Прелесть этого решения в том, что скопированный путь может быть сколь угодно глубоким и содержать вложенные объекты.

Предостережение

Вызов той же функции, что и выше, теперь потребует как topics, так и snapshots ! ( val() возвращает все, что находится под путем). Следующее решение работает каждый раз, когда можно было бы ожидать, и копирует только выбранные пути:

> path_ref.once("value").then(function(dataSnapshot) { dataSnapshot.forEach(function(child){ if (child.key === "topics") { path_ref.child("snapshots").push(child.val())}})});

or

path_ref.once("value").then(
  function(dataSnapshot) { 
    dataSnapshot.forEach(
      function(child){ 
        if (child.key === "topics") {
          path_ref.child("snapshots").push(child.val())
        }
      });
   });

Результат после вызова дважды подряд: