【问题标题】:Preserving the order of an array when using .where in Rails在 Rails 中使用 .where 时保留数组的顺序
【发布时间】:2020-05-09 15:12:51
【问题描述】:

我在 Rails 中将一组 id 传递给 .where,但它的返回方式并没有保留顺序。例如,这里是数组:

2.5.1 :043 > company_ids
 => [83, 79, 52, 44, 82]

我正在查找具有这些公司 ID,但按提供的公司 ID 的顺序返回的所有页面。这是我尝试比较的结果:

2.5.1 :044 > Page.where(company_id: company_ids).pluck(:company_id)
   (1.1ms)  SELECT "pages"."company_id" FROM "pages" WHERE "pages"."company_id" IN ($1, $2, $3, $4, $5)  [["company_id", 83], ["company_id", 79], ["company_id", 52], ["company_id", 44], ["company_id", 82]]
 => [83, 82, 52, 44, 79]

我遇到了这个似乎提供了解决方案的 stackoverflow 帖子 (ActiveRecord.find(array_of_ids), preserving order),但它对我不起作用。当尝试按照 stackoverflow 帖子中的建议使用 Page.where(company_id: company_ids).order("field(company_id, #{company_ids.join ','})") 时,我收到以下错误:

2.5.1 :042 > Page.where(company_id: company_ids).order("field(company_id, #{company_ids.join ','})")
  Page Load (2.0ms)  SELECT  "pages".* FROM "pages" WHERE "pages"."company_id" IN ($1, $2, $3, $4, $5) ORDER BY field(company_id, 83,79,52,44,82) LIMIT $6  [["company_id", 83], ["company_id", 79], ["company_id", 52], ["company_id", 44], ["company_id", 82], ["LIMIT", 11]]
Traceback (most recent call last):
ActiveRecord::StatementInvalid (PG::UndefinedFunction: ERROR:  function field(bigint, integer, integer, integer, integer, integer) does not exist)
LINE 1: ...ts"."company_id" IN ($1, $2, $3, $4, $5) ORDER BY field(comp...
                                                             ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
: SELECT  "pages".* FROM "pages" WHERE "pages"."company_id" IN ($1, $2, $3, $4, $5) ORDER BY field(company_id, 83,79,52,44,82) LIMIT $6

我只是想调用Pages.where(company_id: company_ids) 并根据提供的company_ids 的顺序取回页面。

作为一种解决方法,我正在使用这个:

company_ids = companies.order("full_name ASC").pluck(:id)
pages = []
company_ids.each {|c| pages << Page.find_by(company_id: c)}

但如果有数千条记录,这似乎效率低下。甚至只有数百个。

【问题讨论】:

  • 我认为它们是由 created_at 自动排序的。如果您想要自定义订单,为什么不创建自定义范围以按自定义字段排序?
  • 不熟悉那个过程。我只是想我可以按照另一篇文章中提到的范围附加一些东西。似乎我只是从其他解决方案中遗漏了一些小东西。

标签: ruby-on-rails


【解决方案1】:

问题是您使用的是 MySQL 函数(字段),但您使用的 RDBMS 是 PostgreSQL。

您可以尝试使用position,使用company_id 行和连接的id 数组:

Page.where(company_id: company_ids).order("position(company_id::text in '#{ids.join(',')}')")

用途:

Page.where(company_id: company_ids).order(Arel.sql("position(company_id::text in '#{ids.join(',')}')"))

如果您收到弃用警告。

也存在使用find 的可能性,如文档中所述返回的记录与您提供的ID 的顺序相同。虽然我不知道它是否适用于你的情况。

【讨论】:

    猜你喜欢
    • 2021-03-05
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    相关资源
    最近更新 更多