微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

动态查询构建器堆栈对于 Arel 查询 Rails

如何解决动态查询构建器堆栈对于 Arel 查询 Rails

我正在寻找一种在 Rails 中构建大型动态查询并对给定 ActiveRecord 关系应用更新的方法

例如:

my_big_set = Set.new(big_array)
to_update_relationship = my_big_set.reduce(none) do |query,values_to_check|
                            where('condition = ? and condition_two = ?',values_to_check[:first],values_to_check[:two]).or(query)
                         end
    
to_update_relationship.update_all(field_to_update: true)

to_update_relationship 不是太大时效果很好。但如果它变大,那么 reduce 输出在构造 Arel 查询时会触发 SystemStackerror: stack level too deep 错误

有没有聪明的方法解决它? (除了拆分输入或增加 ruby​​ 系统堆栈大小)。

谢谢

PS:使用 rails 6 和 ruby​​ 2.7

解决方法

您可以使用聚合函数(例如,postgresql STRING_AGG 或 mysql GROUP_CONCAT)来收集 [condition,condition_two] 对,然后检查这些对 IN 您需要的条件。>

假设您使用 postgresql,并且条件类似于 [{first: 1,two: 2},{},...]

pair_conditions = conditions.map {|pair| pair.values.join(",")} # ["1,2",...]
Solution.group(:id,:condition,:condition_two)
.having("STRING_AGG(condition::TEXT || ',' || condition_two::TEXT,'') 
         IN (?)",pair_conditions)

上述查询将 group (condition,condition_two) 并将它们连接为格式为“condition,condition_two”的字符串,以便它们能够与 having 子句上的预定义条件进行比较。>

,

我的最终解决方案是:

my_big_set = Set.new(big_array)
subquery = '(condition = ? and condition_two = ?)'
query = Array.new(my_big_set,subquery).join(' OR ')
query_values = my_big_set.map do |values_to_check|
   [values_to_check[:first],values_to_check[:two]]
end.flatten

where(query,*query_values).update_all(field_to_update: true)

那样,我们构造:

  1. SQL 查询
  2. 传递给 where() 的值
  3. 我们仍然使用活动记录 where() 以防止注入等...

这修正了限制!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。