ruby-on-rails 如何让PostgreSQL函数支持Rails模型?

sdnqo3pr  于 2024-01-09  发布在  Ruby
关注(0)|答案(1)|浏览(152)

我有一个用Rails和PostgreSQL数据库编写的应用程序,我的应用程序有一些复杂的查询,我用它们 Package 在PostgreSQL视图中,这样我就可以将Rails模型“插入”到它们中--在应用程序层面上使事情变得更简单。
到目前为止,上面的方法是成功的,因为我可以通过这些视图所附带的模型来使用ActiveRecord的许多功能。
然而,我正面临着一种情况,我必须优化其中的一些视图,但我发现的唯一方法是将PostgreSQL视图转换为PostgreSQL函数,以便我可以传递参数用作约束(在where子句中)。这种方法使我的视图速度提高了100倍!
但问题是,要调用这些函数,我需要做一些类似Model.find_by_sql('SELECT * FROM my_pg_function(?, ?)')的事情-它返回Model示例的数组。这并不理想,因为我需要方法链(如Model.find_by_sql('SELECT * FROM my_pg_function(?, ?)').find(...))-否则我将不得不在应用程序中进行大量更改。
关于如何使用原始查询以可链接的方式加载数据,有什么想法吗?

eoigrqb6

eoigrqb61#

您应该能够使用一点Arel来实现这个目标。

  1. function = Arel::Nodes::NamedFunction.new('my_pg_function',[1,2])
  2. subquery = Arel::SelectManager.new.project(Arel.star).from(function).as(Model.table_name)
  3. Model.from(subquery)

字符串
这将生成以下查询:

  1. SELECT
  2. models.*
  3. FROM
  4. (SELECT * FROM my_pg_function(1, 2)) models


在这种情况下,这将允许您动态替换函数[1,2]的参数。以及将附加条件链接到“表”,因为它将在过程中返回ActiveRecord::Relation对象。
所以你可以像这样实现:

  1. class MyModel < ApplicationRecord
  2. self.table_name = :my_models
  3. def self.filter(*args)
  4. from(
  5. Arel::SelectManager.new
  6. .project(Arel.star)
  7. .from(Arel::Nodes::NamedFunction.new(
  8. 'my_pg_function',
  9. args.map {|e| Arel::Nodes.build_quoted(e)}))
  10. .as(table_name)
  11. )
  12. end
  13. end


使用像

  1. MyModel.filter(1,2).where(x: 12..).order(:x)

展开查看全部

相关问题