2016-05-16 51 views
0

我有这样的,我有其中有一个JSON领域的产品表的情况下,我必须调用一个方法来更新。因此,有两种方法调用内部update_all自对象中轨

Product.all.each do |pr| 
    pr.update_column(:boolean_tree, pr.change_boolean_tree) 
end 

没有什么不对的除了性能。为了改善我们可以运行原始SQL性能。这肯定会正常工作,但不是以轨道方式。

我在想这是否可以使用update_all这种情况。任何想法 ?

+0

有没有办法从SQL调用红宝石方法('change_boolean_tree')。您可以预先计算一个大型SQL查询的价值观 - 但这是容易批量'INSERT INTO'做的,但我相信,需要一个'UPDATE'一个巨大的'CASE'声明。我会建议反对后者,除非它是一次性脚本。更复杂的是,列是JSON数据。如果您可以在JSON数据的原始SQL中编写等效的'change_boolean_tree',那么这是可行的。正如我所看到的那样,这些是您数据构建的两种选择。 –

+0

@AndrewSchwartz是的,我知道这种做法。正在考虑是否有任何办法。 –

+0

我不确定我了解您的意见。你有没有尝试过这两种方法之一?结果是什么?这些陈述本身在概念上很容易构建,它们非常粗糙,并且没有提供标准的Rails保护或便利,因此很容易将某些东西搞砸。 –

回答

2

据我所知,你将无法使用update_all除非你尝试更新了同样内容的所有记录。当数据库中有很多产品时,指令Product.all会在开始更新之前加载内存中的所有记录。

我建议使用Activerecord的find_in_batches方法(see doc)分批加载产品。

+1

如果您编写SQL片段,则可以使用具有不同内容的'update_all':例如'Model.update_all( “FIELD1 = some_sql_function_on(FIELD2)”)' –

+0

在这种情况下,似乎'change_boolean_tree'是红宝石函数,而不是一个SQL函数。你的称赞会使用ruby函数吗? – Bustikiller

+0

不,你必须编写ruby方法作为SQL函数来使用这种形式。鉴于'boolean_tree'是JSON数据非常困难。另一种选择是像你所建议的那样分批加载,在ruby中预先计算更新的值,然后使用SQL片段中的预计算值在'products.id'上构建'CASE'语句。真的很庞大,但它会起作用。 –