MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB/NoSQL:conservazione della cronologia delle modifiche ai documenti

Bella domanda, anch'io stavo esaminando questo problema.

Crea una nuova versione ad ogni modifica

Mi sono imbattuto nel modulo Versioning del driver Mongoid per Ruby. Non l'ho usato da solo, ma da quello che ho potuto trovare, aggiunge un numero di versione a ciascun documento. Le versioni precedenti sono incorporate nel documento stesso. Lo svantaggio principale è che l'intero documento viene duplicato a ogni modifica , che comporterà l'archiviazione di molti contenuti duplicati quando hai a che fare con documenti di grandi dimensioni. Questo approccio va bene quando hai a che fare con documenti di piccole dimensioni e/o non aggiorni documenti molto spesso.

Memorizza le modifiche solo in una nuova versione

Un altro approccio sarebbe quello di memorizzare solo i campi modificati in una nuova versione . Quindi puoi "appiattire" la tua cronologia per ricostruire qualsiasi versione del documento. Tuttavia, questo è piuttosto complesso, poiché è necessario tenere traccia delle modifiche nel modello e archiviare aggiornamenti ed eliminazioni in modo che l'applicazione possa ricostruire il documento aggiornato. Questo potrebbe essere complicato, poiché hai a che fare con documenti strutturati anziché tabelle SQL piatte.

Memorizza le modifiche all'interno del documento

Ogni campo può anche avere una cronologia individuale. Ricostruire i documenti in una determinata versione è molto più semplice in questo modo. Nella tua applicazione non devi tenere traccia in modo esplicito delle modifiche, ma devi semplicemente creare una nuova versione della proprietà quando ne modifichi il valore. Un documento potrebbe assomigliare a questo:

{
  _id: "4c6b9456f61f000000007ba6"
  title: [
    { version: 1, value: "Hello world" },
    { version: 6, value: "Foo" }
  ],
  body: [
    { version: 1, value: "Is this thing on?" },
    { version: 2, value: "What should I write?" },
    { version: 6, value: "This is the new body" }
  ],
  tags: [
    { version: 1, value: [ "test", "trivial" ] },
    { version: 6, value: [ "foo", "test" ] }
  ],
  comments: [
    {
      author: "joe", // Unversioned field
      body: [
        { version: 3, value: "Something cool" }
      ]
    },
    {
      author: "xxx",
      body: [
        { version: 4, value: "Spam" },
        { version: 5, deleted: true }
      ]
    },
    {
      author: "jim",
      body: [
        { version: 7, value: "Not bad" },
        { version: 8, value: "Not bad at all" }
      ]
    }
  ]
}

Contrassegnare parte del documento come eliminata in una versione è comunque alquanto imbarazzante. Potresti introdurre uno state campo per le parti che possono essere eliminate/ripristinate dalla tua applicazione:

{
  author: "xxx",
  body: [
    { version: 4, value: "Spam" }
  ],
  state: [
    { version: 4, deleted: false },
    { version: 5, deleted: true }
  ]
}

Con ciascuno di questi approcci è possibile archiviare una versione aggiornata e ridotta in una raccolta e i dati della cronologia in una raccolta separata. Ciò dovrebbe migliorare i tempi di query se sei interessato solo all'ultima versione di un documento. Ma quando hai bisogno sia della versione più recente che dei dati storici, dovrai eseguire due query, anziché una. Quindi la scelta di utilizzare una singola raccolta rispetto a due raccolte separate dovrebbe dipendere da quanto spesso l'applicazione necessita delle versioni storiche .

La maggior parte di questa risposta è solo una discarica cerebrale dei miei pensieri, in realtà non ho ancora provato nulla di tutto ciò. Ripensandoci, la prima opzione è probabilmente la soluzione più semplice e migliore, a meno che il sovraccarico di dati duplicati non sia molto significativo per la tua applicazione. La seconda opzione è piuttosto complessa e probabilmente non vale la pena. La terza opzione è fondamentalmente un'ottimizzazione dell'opzione due e dovrebbe essere più facile da implementare, ma probabilmente non vale lo sforzo di implementazione a meno che tu non possa davvero andare con l'opzione uno.

Non vedo l'ora di ricevere feedback su questo e sulle soluzioni di altre persone al problema :)