Tengo una fuente de datos que proporciona una lista de objetos y sus propiedades (un archivo CSV, pero eso no importa). Cada vez que se ejecuta mi programa, necesita extraer una nueva copia de la lista de objetos, compararla con la lista de objetos (y sus propiedades) almacenadas en la base de datos y actualizar la base de datos según sea necesario.

Tratar con nuevos objetos es fácil: la fuente de datos le da a cada objeto un número de identificación secuencial, verifica el número de identificación superior en la nueva información contra la base de datos y listo. Estoy buscando sugerencias para los otros casos, cuando algunas de las propiedades de un objeto han cambiado o cuando se ha eliminado un objeto.

Una solución ingenua sería extraer todos los objetos de la base de datos y obtener el complemento de la intersección de los dos conjuntos (antiguo y nuevo) y luego examinar esos resultados, pero eso parece que no sería muy eficiente si los conjuntos obtienen grande. ¿Algunas ideas?

0
Dan 19 jun. 2009 a las 22:09

4 respuestas

La mejor respuesta

El enfoque estándar para grandes cantidades de datos equivale a esto.

Asumiremos que list_1 es el "maestro" (sin duplicados) y list_2 son las "actualizaciones" que pueden tener duplicados.

iter_1 = iter( sorted(list_1) ) # Essentially SELECT...ORDER BY
iter_2 = iter( sorted(list_2) )
eof_1 = False
eof_2 = False
try:
    item_1 = iter_1.next()
except StopIteration:
    eof_1= True
try:
    item_2 = iter_2.next()
except StopIteration:
    eof_2= True
while not eof_1 and not eof_2:
    if item_1 == item_2:
        # do your update to create the new master list.
        try:
            item_2 = iter_2.next()
        except StopIteration:
            eof_2= True
    elif item_1 < item_2:
        try:
            item_1 = iter_1.next()
        except StopIteration:
            eof_1= True
    elif item_2 < item_1:
        # Do your insert to create the new master list.
        try:
            item_2 = iter_2.next()
        except StopIteration:
            eof_2= True
assert eof_1 or eof_2
if eof_1:
    # item_2 and the rest of list_2 are inserts.
elif eof_2:
    pass
else:
    raise Error("What!?!?") 

Sí, implica un tipo potencial. Si list_1 se mantiene ordenado cuando lo vuelve a escribir en el sistema de archivos, eso ahorra un tiempo considerable. Si list_2 puede acumularse en una estructura que la mantiene ordenada, eso ahorra un tiempo considerable.

Perdón por la palabrería, pero necesita saber qué iterador generó el StopIteration, por lo que no puede (trivialmente) envolver todo el ciclo while en un bloque grande-try-old.

1
S.Lott 19 jun. 2009 a las 19:11

¿No hay forma de mantener un campo de "última modificación"? Eso es lo que parece que realmente está buscando: una copia de seguridad incremental, basada en la última vez que se ejecutó la copia de seguridad, en comparación con la última vez que se modificó / eliminó (/ agregó) un objeto.

1
user447688user447688 19 jun. 2009 a las 18:25

Necesita tener marcas de tiempo tanto en su base de datos como en su archivo CSV. La marca de tiempo debe mostrar los datos cuando se actualizó el registro y usted debe comparar las marcas de tiempo del registro con las mismas ID para decidir si necesita actualizarlo o no.

En cuanto a su idea sobre la intersección ... ¡Debe hacerse al revés! Debe importar todos los datos de CSV a la tabla temporal y hacer la intersección entre 2 tablas de bases de datos SQL. Si usa Oracle o MS SQL 2008 (no estoy seguro para 2005) encontrará una palabra clave MERGE muy útil, por lo que puede escribir SQL con menos esfuerzo y luego gastará para fusionar datos en otro lenguaje de programación.

1
Bogdan_Ch 19 jun. 2009 a las 18:33

Cuando coloque la lista en su programa, repita la lista haciendo una consulta basada en una propiedad de columna en la tabla de la base de datos que se asigna a la misma propiedad del objeto de la lista como ObjectName. O podría cargar toda la tabla en una lista y comparar la lista de esa manera. Supongo que tiene algo único sobre el objeto que existe además del ID que asigna la base de datos.

Si ese objeto no se encuentra en la tabla a través de la consulta, cree una nueva entrada. Si se encuentra como se menciona en FogleBird, tenga un hash calculado o CRC almacenado para ese objeto en la tabla que pueda comparar con el objeto en la lista (ejecute el cálculo en el objeto). Si los hashes no coinciden, actualice ese objeto con el de la lista.

0
Jay Atkinson 19 jun. 2009 a las 18:26