Удалить базу данных старше 2 часов

Я хотел бы удалить все данные старше двух часов. В настоящее время на стороне клиента я перебираю все данные и запускаю удаление для всех старых. Когда я делаю это, функция db.on('value') вызывается каждый раз, когда что-то удаляется. Кроме того, все будет удалено только при подключении клиента, и что может произойти, если два клиента подключаются одновременно?

Где я могу установить что-то, что удаляет старые данные? У меня есть отметка времени внутри каждого объекта, созданного JavaScript Date.now().

4 ответа

Firebase не поддерживает запросы с динамическим параметром, таким как "два часа назад". Однако он может выполнить запрос для определенного значения, например, "после 14 августа 2015 г., 7:27:32 AM".

Это означает, что вы можете периодически запускать фрагмент кода для очистки элементов, которые старше 2 часов:

var ref = firebase.database().ref('/path/to/items/');
var now = Date.now();
var cutoff = now - 2 * 60 * 60 * 1000;
var old = ref.orderByChild('timestamp').endAt(cutoff).limitToLast(1);
var listener = old.on('child_added', function(snapshot) {
    snapshot.ref.remove();
});

Как вы заметите, я использую child_added вместо value, и я limitToLast(1), Когда я удаляю каждого ребенка, Firebase запустит child_added для нового "последнего" элемента до тех пор, пока после точки отсечения больше не будет элементов.

Обновление: если вы хотите запустить этот код в облачных функциях для Firebase:

exports.deleteOldItems = functions.database.ref('/path/to/items/{pushId}')
.onWrite((change, context) => {
  var ref = change.after.ref.parent; // reference to the items
  var now = Date.now();
  var cutoff = now - 2 * 60 * 60 * 1000;
  var oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
  return oldItemsQuery.once('value', function(snapshot) {
    // create a map with all children that need to be removed
    var updates = {};
    snapshot.forEach(function(child) {
      updates[child.key] = null
    });
    // execute all updates in one go and return the result to end the function
    return ref.update(updates);
  });
});

Эта функция срабатывает всякий раз, когда данные записываются в /path/to/items, поэтому дочерние узлы будут удалены только при изменении данных.

Этот код теперь также доступен в functions-samples репо

У меня есть облачная функция, запускаемая по протоколу http, которая удаляет узлы в зависимости от того, когда они были созданы, и срока их действия.

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

Затем у меня есть эта http-функция, запускаемая облаком:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

/**
 * @function HTTP trigger that, when triggered by a request, checks every message of the database to delete the expired ones.
 * @type {HttpsFunction}
 */
exports.removeOldMessages = functions.https.onRequest((req, res) => {
    const timeNow = Date.now();
    const messagesRef = admin.database().ref('/messages');
    messagesRef.once('value', (snapshot) => {
        snapshot.forEach((child) => {
            if ((Number(child.val()['timestamp']) + Number(child.val()['duration'])) <= timeNow) {
                child.ref.set(null);
            }
        });
    });
    return res.status(200).end();
});

Вы можете создать задание cron, которое каждые X минут отправляет запрос на URL этой функции: https://cron-job.org/en/

Но я предпочитаю запускать свой собственный скрипт, который делает запрос каждые 10 секунд:

watch -n10 curl -X GET https://(your-zone)-(your-project-id).cloudfunctions.net/removeOldMessages

В последней версии Firebase API ref() изменен на ref

var ref = new Firebase('https://yours.firebaseio.com/path/to/items/');
var now = Date.now();
var cutoff = now - 2 * 60 * 60 * 1000;
var old = ref.orderByChild('timestamp').endAt(cutoff).limitToLast(1);
var listener = old.on('child_added', function(snapshot) {
    snapshot.ref.remove();
});

Если у кого-то будет такая же проблема, но в Firestore. Я сделал небольшой скрипт, который сначала считывал документы в console.log, а затем удалял документы из коллекции сообщений старше 24 часов. Использование https://cron-job.org/en/ для обновления веб-сайта каждые 24 часа, и все. Код ниже.

var yesterday = firebase.firestore.Timestamp.now();
  yesterday.seconds = yesterday.seconds - (24 * 60 * 60);
  console.log("Test");
  db.collection("messages").where("date",">",yesterday)
      .get().then(function(querySnapshote) {
        querySnapshote.forEach(function(doc) {
          console.log(doc.id," => ",doc.data());
        });
      })
  .catch(function(error) {
        console.log("Error getting documents: ", error);
  });

  db.collection("messages").where("date","<",yesterday)
    .get().then(function(querySnapshote) {
      querySnapshote.forEach(element => {
        element.ref.delete();
      });
    })

Вы можете посмотреть на планирование функций Firebase с помощью Cron Jobs. Эта ссылка показывает, как запланировать запуск облачной функции Firebase с фиксированной скоростью. В запланированной функции Firebase вы можете использовать другие ответы в этой теме, чтобы запросить старые данные и удалить их.

Другие вопросы по тегам