如何从按id的特定顺序排序的记录数组中获得ActiveRecord::关系?

时间:2021-04-30 15:15:49

I have a Rails engine that defines a class method top(count) on a model of choice. What this method does is grab count IDs from a sorted set (ZSET) in Redis. The idea is that each item of this model has a score, and this method is to return the "best" records. The method essentially looks like this:

我有一个Rails引擎,它在选择的模型上定义类方法top(count)。这个方法的作用是从Redis中的排序集(ZSET)获取计数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

As you can see, I currently sort the records after the fact because databases (or the adapters) tend not to maintain order when finding by multiple IDs. For instance, Model.where('ID IN (?)', ids) will sort by ascending IDs rather than the order of the passed IDs.

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

Sorting the items returns an Array, but I'd like this method to return an ActiveRecord::Relation instead so that my users can chain it with other ActiveRecord query methods. Is there a way I can use the built-in ActiveRecord query methods to maintain order from my array of IDs? Or alternatively, is there a way to construct an ActiveRecord::Relation from an array of records?

排序项返回一个数组,但是我希望这个方法返回一个ActiveRecord::关系,以便我的用户可以将它与其他ActiveRecord查询方法链接起来。是否有一种方法可以使用内置的ActiveRecord查询方法来维护id数组的顺序?或者,是否有一种方法可以从记录数组构造ActiveRecord::关系?

1 个解决方案

#1


4  

It really depends on the underlying database you are using. I do not think rails has a pretty way to do this.

这实际上取决于您使用的基础数据库。我认为rails没有一个很好的方法来实现这一点。

I have an application where I am doing the same thing as you. Storing ids in a Redis ZSET and then needing to fetch them in that order. Since we are using MySql we can take advantage of the field function.

我有一个和你做同样事情的应用程序。将id存储在Redis ZSET中,然后需要按此顺序获取它们。因为我们使用的是MySql,所以我们可以利用field函数。

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

PS: Make sure your order variable is sanitized!

注意:确保您的订单变量已被清除!

#1


4  

It really depends on the underlying database you are using. I do not think rails has a pretty way to do this.

这实际上取决于您使用的基础数据库。我认为rails没有一个很好的方法来实现这一点。

I have an application where I am doing the same thing as you. Storing ids in a Redis ZSET and then needing to fetch them in that order. Since we are using MySql we can take advantage of the field function.

我有一个和你做同样事情的应用程序。将id存储在Redis ZSET中,然后需要按此顺序获取它们。因为我们使用的是MySql,所以我们可以利用field函数。

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

PS: Make sure your order variable is sanitized!

注意:确保您的订单变量已被清除!