sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo mantener el historial de edición de un campo de cadena grande en una base de datos relacional

Una solución en la que estoy trabajando ahora mismo, que funciona bien hasta ahora, implementa el diseño que propuse en la pregunta

Compartiré los detalles de mi implementación aquí

Para crear deltas y usar para reconstruir el texto completo, estoy usando el fantástico biblioteca de google-diff-match-patch . Puede leer la documentación de la API independiente de la implementación. para comprender mejor los ejemplos de código a continuación, aunque de todos modos es bastante legible.

Google-diff-match-parche tiene implementaciones de Java y JS, por lo que puedo usarlo para calcular los deltas con Java en el servidor. Elegí convertir cada delta en una cadena para que pueda almacenarse fácilmente en la base de datos y consumirse fácilmente por la biblioteca JS en el cliente. Más sobre esto a continuación.

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);
}

N.B. algo que me tomó un tiempo descubrir fue cómo descargar la compilación oficial de google-diff-match-patch utilizando experto. No está en el repositorio central de maven, sino en su propio repositorio en googlecode.com. Solo para tener en cuenta, algunas personas lo han bifurcado y han puesto sus versiones bifurcadas en maven central, pero si realmente desea la versión oficial, puede obtenerla agregando el repositorio y la dependencia en su pom.xml de la siguiente manera

<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>

Para el front-end, paso el texto completo de la última publicación del blog, junto con una cadena de deltas que retroceden en el tiempo que representan cada edición, y luego reconstruyo el texto completo de cada versión en el navegador en JS.

Para obtener la biblioteca, estoy usando npm + browserify. La biblioteca está disponible en npm como diff-match-patch . La versión 1.0.0 es la única versión.

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];
}

Y eso es todo, funciona fantásticamente.

En términos de almacenar las ediciones de las publicaciones del blog, solo uso una tabla BLOG_POST_EDITS donde almaceno la identificación de la publicación del blog, una marca de tiempo de cuándo se realizó la edición (que luego utilizo para ordenar las ediciones correctamente para hacer la cadena al reconstruir las versiones de texto completo en el cliente) y el delta inverso entre la versión en vivo actual publicación de blog en BLOG_POST tabla y la versión editada entrante de la entrada del blog.

Elegí almacenar una 'cadena' de deltas porque se adapta bien a mi caso de uso y es más simple en el extremo del código del servidor. Significa que para reconstruir la versión M de N, tengo que enviar al cliente una cadena de deltas N-(M-1) desde el texto completo de la publicación de blog en vivo a la versión M. Pero en mi caso de uso sucede que quiero enviar la cadena completa cada vez, de todos modos, así que está bien.

Para obtener una eficiencia ligeramente mejor por cable para solicitar versiones específicas, todos los deltas podrían recalcularse desde la nueva versión de publicación de blog editada hasta cada versión (restaurada) cada vez que se realiza una edición, pero esto significaría más trabajo y complejidad en el servidor.