PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come mantenere la cronologia delle modifiche di campi di stringhe di grandi dimensioni nel database relazionale

Una soluzione su cui sto lavorando in questo momento, che finora funziona bene, implementa il design che ho proposto nella domanda

Condividerò qui le specifiche della mia implementazione

Per creare delta e utilizzare per ricostruire il testo completo, sto usando il fantastico libreria di patch di google-diff-match . Puoi leggere la documentazione API indipendentemente dall'implementazione per comprendere meglio gli esempi di codice di seguito, anche se è comunque abbastanza leggibile.

google-diff-match-patch ha implementazioni Java e JS, quindi posso usarlo per calcolare i delta con Java sul server. Ho scelto di convertire ogni delta in una stringa sia in modo che possa essere facilmente archiviato nel database e facilmente consumato dalla libreria JS sul client. Maggiori informazioni su questo di seguito.

public String getBackwardsDelta(String editedBlogPost, String existingBlogPost) {
    diff_match_patch dmp = new diff_match_patch();
    LinkedList<diff_match_patch.Patch> patches = 
        dmp.patch_make(editedBlogPost, existingBlogPost);
    return dmp.patch_toText(patches);
}

NB qualcosa che mi ci è voluto un po' per capire è stato come eliminare la build ufficiale di google-diff-match-patch usando Maven. Non è nel repository centrale di Maven, ma nel proprio repository su googlecode.com. Solo per notare, alcune persone lo hanno biforcato e inserito le loro versioni biforcate in Maven Central, ma se vuoi davvero la versione ufficiale puoi ottenerla aggiungendo il repository e la dipendenza nel tuo pom.xml come segue

<repository>
  <id>google-diff-patch-match</id>
  <name>google-diff-patch-match</name>
  <url>https://google-diff-match-patch.googlecode.com/svn/trunk/maven/</url>
</repository>

<dependency>
  <groupId>diff_match_patch</groupId>
  <artifactId>diff_match_patch</artifactId>
  <version>current</version>
</dependency>

Per il front-end, passo l'ultimo post del blog full-text, insieme a una catena di delta che vanno indietro nel tempo che rappresentano ogni modifica, quindi ricostruisco il testo completo di ciascuna versione nel browser in JS.

Per ottenere la libreria, sto usando npm + browserify. La libreria è disponibile su npm come diff-match-patch . La versione 1.0.0 è l'unica versione.

getTextFromDelta: function(originalText, delta) {
  var DMP = require('diff-match-patch'); // get the constructor function
  var dmp = new DMP();
  var patches = dmp.patch_fromText(delta);
  return dmp.patch_apply(patches, originalText)[0];
}

E il gioco è fatto, funziona in modo fantastico.

In termini di memorizzazione delle modifiche dei post del blog, utilizzo semplicemente una tabella BLOG_POST_EDITS dove memorizzo l'ID del post del blog, un timestamp di quando è stata apportata la modifica (che in seguito utilizzo per ordinare correttamente le modifiche per creare la catena durante la ricostruzione delle versioni full-text sul client) e il delta all'indietro tra il live corrente post del blog nel BLOG_POST tabella e la versione modificata in arrivo del post del blog.

Ho scelto di memorizzare una "catena" di delta perché si adatta bene al mio caso d'uso ed è più semplice per quanto riguarda il codice del server. Significa che per ricostruire la versione M di N, devo inviare al cliente una catena di delta N-(M-1) dal post del blog live full-text alla versione M. Ma nel mio caso d'uso mi capita di voglio comunque inviare l'intera catena ogni volta, quindi va bene.

Per un'efficienza over-the-wire leggermente migliore per la richiesta di versioni specifiche, tutti i delta potrebbero essere ricalcolati dalla nuova versione modificata del post del blog a ciascuna versione (ripristinata) ogni volta che viene apportata una modifica, ma ciò significherebbe più lavoro e complessità sul server.