← blog
JavaScript Firestore RTDB Pattern misto

Centro notifiche multi-categoria: Firestore + RTDB nello stesso drawer

Come scegliere il database giusto per categoria di notifica, e combinare una query Firestore a lettura singola con listener RTDB real-time nello stesso pannello, senza conflitti.

Il problema

Un centro notifiche con piΓΉ categorie (ferie, calendario, chat, promemoria) spesso ha dati che vivono in database diversi con caratteristiche diverse: alcuni vanno letti una volta sola, altri devono aggiornarsi in tempo reale. Usare lo stesso pattern per tutto spreca letture o introduce listener inutili.

Firestore: lettura singola con filtri multipli

Per categorie dove lo storico non cambia spesso (es. richieste ferie), una query Firestore con .get() β€” non .onSnapshot() β€” evita di tenere aperto un listener inutile.

notifiche-ferie.js β€” query Firestore (lettura singola)
const cutoff = Date.now() - 90 * 24 * 60 * 60 * 1000;
const tipi = [
  'ferie_richiesta', 'ferie_approvata',
  'ferie_rifiutata', 'ferie_annullata'
];

db.collection('activityLog')
  .where('operatore', '==', currentUser)
  .where('tipo', 'in', tipi)
  .where('ts', '>=', cutoff)
  .get()   // una sola lettura, non real-time
  .then(snap => snap.docs.map(d => ({ id: d.id, ...d.data() })));

RTDB: listener real-time su nodi giΓ  esistenti

Calendario, promemoria e chat invece vivono sul Realtime Database β€” nodi piccoli, giΓ  strutturati per letture veloci. Agganciarsi con .on('value') su nodi esistenti non aggiunge costo significativo, ed Γ¨ la scelta giusta quando i dati cambiano spesso e l'utente deve vederli aggiornarsi senza refresh.

notifiche-calendario.js β€” listener RTDB real-time
const ref = db.ref('calendario/' + reparto);

ref.on('value', snapshot => {
  const eventi = snapshot.val() || {};

  // Filtra: solo eventi giΓ  scattati, creati dall'utente o del suo reparto
  const visibili = Object.entries(eventi)
    .filter(([id, ev]) =>
      ev.firedAt && (ev.creatoDa === currentUser || ev.reparto === userReparto)
    );

  renderNotificheCalendario(visibili);
});

// Da chiamare allo smontaggio del componente / cambio utente
function cleanup() { ref.off('value'); }

Regola pratica: dati che cambiano raramente e vanno solo consultati β†’ Firestore .get(). Dati che devono aggiornarsi live nell'interfaccia senza azione dell'utente β†’ RTDB .on('value').

Attenzione al bootstrap: in una PWA con "ricordami", i listener real-time avviati al login manuale devono essere avviati anche nel percorso di restore sessione β€” altrimenti metΓ  degli utenti lavora con notifiche silenziosamente disattivate dopo un refresh.

Articolo correlato
Centro notifiche PWA: Firebase, Firestore e drawer a categorie β€” caso reale
β†’