Один из лучших приемов Firebase - избегать глубоко вложенных структур данных, которые могут создавать проблемы, связанные с распределением связанных данных повсюду.

Как и в традиционной базе данных SQL, если вы не будете осторожны при удалении данных, вы можете легко получить потерянные строки. Это не хорошо. Большинство современных реляционных баз данных поддерживают своего рода «триггеры» для выполнения самых разных задач: в нашем случае автоматическое удаление строк в других таблицах при удалении внешних ключей, которые ссылаются на них.

Поэтому, если мы следуем лучшим практикам Firebase в очень простой системе комментариев, мы будем хранить пользователей и сообщения в отдельных корневых объектах, например:

{
  "users": {
    "-KgDDqAi9ftdnPuEQB9b": {
      "userName": "jason",
      "email": "[email protected]"
    }
  },
  "posts": {
    "-KmDDqU49ftdnPuEQB6b": {
      "userId": "-KgDDqAi9ftdnPuEQB9b",
      "userName": "jason",
      "body": "Wow! These Firebase Functions are really great!"
    }
  }
}

Что произойдет, если мы удалим пользователя «jason»?

firebase.database().ref("users/-KgDDqAi9ftdnPuEQB9b").remove();

Отлично ... теперь мы просто осиротели пост !! Мы могли бы добавить в наше приложение дополнительную логику, чтобы также удалить сообщения этого пользователя.

firebase.database().ref("posts")
  .orderByChild("userId")
  .equalTo("-KgDDqAi9ftdnPuEQB9b")
  .on("value")
  .then(function(snapshot) {
    snapshot.forEach(function(childSnapshot) { 
      childSnapshot.remove();
    });
  });

Помимо №1: если вы сделаете это, вы должны обязательно добавить соответствующие индексы. Помимо № 2: Было бы неплохо, если бы был лучший способ выполнять такие запросы без forEach для удаления каждой строки по отдельности. * подсказка * Команда Firebase, вы слушаете?

Вы можете подумать, что это достаточно просто. Эта логика запроса / для каждого / удаления может подойти для простого приложения. Но что, если есть много других связанных с пользователем объектов, которые также необходимо удалить? Теперь ваше приложение начинает сильно забиваться подобными домашними делами!

А теперь представьте, если бы вы начали использовать одну и ту же базу данных Firebase Realtime из нескольких приложений. Возможно, на сайте приложение для iOS, приложение для Android, канал OTT Roku - кто знает! Итак, в этот момент вы воспроизводите такую ​​логику во многих местах, и это становится просто смехотворным!

Должен быть способ попроще! С Cloud Functions для Firebase это возможно!

Я не собираюсь говорить о том, что такое функции Firebase и как их настраивать, поскольку я немного говорил об этом в своей последней статье и поскольку Firebase имеет отличную документацию. Итак, я предполагаю, что вы понимаете концепцию или можете самостоятельно получить инструкции по их настройке.

let functions = require('firebase-functions');
// This will run when a row is changed that matches this pattern
exports.onDeletedRow = functions.database.ref('/users/{userId}')
  .onChange(event => {

    // Exit if this item exists... if so it was not deleted!
    if (event.data.exists()) {
        return;
    }

    // Remove all posts from that user
    event.data.adminRef.getRoot().ref("/posts")
        .orderByChild("userId")
        .equalTo(event.params.userId)
        .on("value")
        .then(function(snapshot) {
            snapshot.forEach(function(childSnapshot) {
                childSnapshot.remove();
            });
        });

});

Приведенный выше код устанавливает триггер нашего события для каждого изменения объекта с шаблоном users / userId (независимо от того, какое изменение). Затем мы убеждаемся, что это событие удаления, убеждаясь, что текущие данные больше не существуют. Наконец, мы запрашиваем все сообщения с этим идентификатором пользователя и удаляем их.

Несколько моментов, которые могут сбить с толку:

  • event.data.adminRef = Получить ссылку на текущий элемент с полными правами администратора на чтение / запись
  • getRoot () = Получить ссылку на объект корневой базы данных
  • event.params.userId = Это дает нам идентификатор этого пользователя на основе параметра, который мы добавили в шаблон в '/ users / {userId}'.

Как вы можете видеть, это на самом деле не спасает нас ни одной строчки кода как есть, но то, что он делает, намного лучше разделяет проблемы. И, кроме того, как только вы настроите этот триггер, он сработает, даже если вы вручную удалите пользователя в консоли Firebase (или из любого другого места). Гораздо лучше, чтобы эта логика жила на самом высоком, максимально абстрактном уровне.

Это только начало. Очевидно, вы также можете использовать триггеры для синхронизации денормализованных данных. Вы можете использовать их для автоматического заполнения созданных или последних обновленных значений типа. Автоматически создавать журналы аудита. Отправляйте данные в полнотекстовые поисковые системы. Очистить кеши. Все, что вы можете себе представить.

Firebase Functions - это такой ценный ключ, которого не хватало, что действительно увеличивает ценность продукта! Теперь займемся кодированием!