2011-10-18 18 views
7

Tengo una aplicación Rails 3 donde tengo que ingerir un archivo XML proporcionado por un sistema externo en una base de datos PostgreSQL. Me gustaría usar algo como ActiveRecord-Import, pero parece que esto no maneja las capacidades de Postgres, y algunos de los registros que voy a ingerir ya existirán, pero deberán actualizarse.upsert a granel con Ruby on Rails

La mayor parte de lo que estoy leyendo recomienda escribir SQL sobre la marcha, pero esto parece ser un problema que puede haber sido resuelto ya. Simplemente no puedo encontrarlo.

Gracias.

+0

No estoy seguro de que Rails sea la herramienta adecuada para esto. ¿Ha considerado hacer esto fuera de Rails usando las herramientas XML y PostgreSQL existentes? –

+0

Una vez en la base de datos, los datos insertados se convierten en modelos utilizados para otros fines, editables a través de la web, etc., tenemos validaciones y asociaciones en el modelo. Me preocupa que la ruptura de los raíles nos haga duplicar mucho trabajo y dificultar el mantenimiento en el futuro. –

+3

Si desea que se ejecuten las validaciones de ActiveRecord, tendrá que insertar un registro a la vez. Si desea una actualización masiva + validaciones, entonces tendrá que configurar las validaciones/restricciones en el lado db. Si desea eficiencia en este caso, puede que tenga que comprometerse en la mantenibilidad del código –

Respuesta

-1

Es una cosa de dos pasos. Primero debe buscar el archivo XML. Si es provisto por un usuario a través de un formulario que tiene suerte para usted, de lo contrario debe buscarlo utilizando la lib HTTP estándar de ruby ​​o alguna gema como Mechanize (que en realidad es genial)

Lo segundo es realmente fácil. Uno lee todo el XML en una cadena y luego se puede convertir en un hash con esta pice de código:

Hash.from_xml(xml_string) 

A continuación, puede analizar y trabajar con los datos ...

+0

Estamos utilizando happymapper para analizar el XML y eso está funcionando muy bien. Lo que dificulta esto es que el número de objetos que queremos ingerir lo hace muy lento si insertamos/actualizamos cada objeto uno por uno. –

7

Usted puede hacer upserting en MySQL y PostgreSQL con upsert.

Si usted está buscando la velocidad pura, podría utilizar nokogiri y upsert.

Podría ser más fácil para importar los datos utilizando data_miner, que utiliza nokogiri y upsert internamente.

+0

Desearía haber visto esta respuesta antes – sheerun

1

Si usted está en PostgreSQL 9.1 que puedes usar expresiones de tabla común grabables. Algo así como:

WITH updates (id) AS (
    UPDATE mytable SET ..... 
     WHERE .... 
    RETURNING id 
) 
INSERT INTO mytable (....) 
SELECT ... 
    FROM mytemptable 
WHERE id NOT IN (select id from updates); 

En este caso, el proceso a granel se adelgaza en una tabla temporal en primer lugar, a continuación, se tratará de actualizar los registros de la TempTable acuerdo con su lógica, e inserte el resto.