2011-10-18 80 views
7

我有一个Rails 3应用程序,我需要将外部系统提供的XML文件提取到Postgres数据库中。我想使用类似ActiveRecord-Import的东西,但是这似乎不能处理Postgres的upsert功能,并且我将要摄取的一些记录已经存在,但需要更新。Bulk onsert with Ruby on Rails

我正在阅读的大部分内容都建议尽快编写SQL,但这似乎是一个可能已经解决的问题。我无法找到它。

谢谢。

+0

我不确定Rails是否正确。您是否考虑过使用现有的XML和PostgreSQL工具在Rails之外进行此操作? –

+0

一旦进入数据库,插入的数据就成为用于其他目的的模型,可以通过网络进行编辑等等,我们对模型进行验证和关联。我担心打破轨道会导致我们复制大量的工作,并使维护变得困难。 –

+3

如果您希望ActiveRecord验证运行,您将不得不一次插入一条记录。如果你想批量更新+验证,那么你将不得不在数据库端设置验证/约束。如果你想在这种情况下效率,你可能不得不妥协代码可维护性 –

回答

-1

它是一个两步走的事情。首先,您需要获取XML文件。如果它由用户通过一种形式提供给你的运气,否则你需要使用标准的HTTP库来获取它,或者像机械化的一些宝石(实际上真的很棒)。

第二件事很简单。你读所有的XML转换成字符串,然后你可以将其转换成一个哈希这个PICE代码:

Hash.from_xml(xml_string) 

然后你可以分析和处理数据的工作...

+0

我们正在使用happymapper来解析XML,并且工作得很好。造成这种困难的因素是,如果我们逐一插入/更新每个对象,我们想要摄取的对象数量会非常缓慢。 –

7

你可以做upserting在MySQL和PostgreSQL上使用upsert

如果你正在寻找原始速度,你可以使用nokogiri和upsert。

使用data_miner导入数据可能更容易,该数据在内部使用nokogiri和upsert。

+0

我希望我早点看到了这个答案 – sheerun

1

如果您使用的是PostgreSQL 9.1,则应使用可写的公用表表达式。喜欢的东西:

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

在这种情况下,你批量过程中临时表变薄第一,那么它会尝试按照你的逻辑从不是Temptable更新记录,并插入休息。