【问题标题】:How can I get an ActiveRecord::Relation from an array of records sorted in a specific order of their IDs?如何从按 ID 的特定顺序排序的记录数组中获取 ActiveRecord::Relation?
【发布时间】:2012-06-29 11:35:37
【问题描述】:

我有一个 Rails 引擎,它在所选模型上定义了一个类方法 top(count)。此方法的作用是从 Redis 中的排序集 (ZSET) 中获取 count ID。这个想法是这个模型的每个项目都有一个分数,这个方法是返回“最好”的记录。该方法基本上如下所示:

def self.top(count = 1)
  ids = redis.zrevrange(self.score_set, 0, count - 1)
  items = self.find ids

  if count == 1
    return items.first
  else
    return items.sort { |x, y| ids.index(x.id) <=> ids.index(y.id) }
  end
end

如您所见,我目前在事后对记录进行排序,因为数据库(或适配器)在通过多个 ID 查找时往往不会保持顺序。例如,Model.where('ID IN (?)', ids) 将按 ID 升序排序,而不是按传递 ID 的顺序。

排序项目返回一个Array,但我希望这个方法返回一个ActiveRecord::Relation,以便我的用户可以将它与其他ActiveRecord 查询方法链接。有没有办法可以使用内置的 ActiveRecord 查询方法来维护我的 ID 数组的顺序?或者,有没有办法从记录数组构造ActiveRecord::Relation

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 activerecord


    【解决方案1】:

    这实际上取决于您使用的底层数据库。我不认为 Rails 有一个很好的方法来做到这一点。

    我有一个应用程序,我正在和你做同样的事情。将 id 存储在 Redis ZSET 中,然后需要按该顺序获取它们。由于我们使用的是 MySql,我们可以利用 field function

    Model.where('id in (?)', ids).order("field(id, #{order})")
    

    PS:确保您的 order 变量已清理!

    【讨论】:

    • 这对 MySQL 很有效,是的,但我的 gem 需要与数据库无关。我想我可能会放弃,只返回一个数组。我认为没有一种方法可以适用于每个主要数据库。
    • 还有另一种方法,虽然效率不高,但仍然有效:stackoverflow.com/a/15564039/204452
    猜你喜欢
    • 1970-01-01
    • 2011-06-22
    • 2013-02-14
    • 2021-11-04
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多