1

假设我有一个User带有一个字段的 a name,哪个 has_many teams,一个Team是属于一个的,一个user属于一个的sport。ASport有一个字段name和 has_many teams

我想遍历,做一些事情,并收集按 排序的sports数组。teamsnameuser

result = []
Sport.asc(:name).each do |spt|
  # some other stuff not relevant to this question but that
  # justifies my looping through each sport.
  spt.teams.asc(:'user.name').each { |t| result << t }
end

这会运行,但是排序sports是预期的,但是团队的顺序result没有按我预期的那样排序。

Mongoid使用按关系值对集合进行排序的正确方法是什么?

4

1 回答 1

3

我不认为有办法用 Mongoid 做到这一点。如果您作为排序依据的字段是嵌入文档的一部分,它可能会起作用,但在这种情况下,您使用的是引用文档则不然。

我想您可能在这里有两个选择,效率较低的方法是仅对 ruby​​ 中的团队集合进行排序:

sport.teams.sort{|t1, t2| t1.user.name <=> t2.user.name}.each{ |team| result << team }

更好的,可以说是更“MongoDB-y”的解决方案是使用before_save回调在每个团队中缓存用户名,然后使用它对团队进行排序:

# app/models/team.rb
class Team
  include Mongoid::Document

  field :user_name, :type => String

  before_save :update_user_name

  protected
  def update_user_name
    self.user_name = self.user.name if self.user
  end
end

然后你可以这样做:

spt.teams.asc(:user_name).each { |t| result << t }

显然,如果用户的名称字段是可变的,那么只要用户的名称字段发生更改,您就会触发它以保存每个子团队。

class User
  after_save :update_teams_if_name_changed

  def update_teams_if_name_changed
    if self.name_changed?
      self.teams.each { |team| team.save }
    end
  end
end

鉴于维护起来并不简单,这可以说是使用观察者而不是回调的好选择,但你明白了。

于 2013-05-09T00:24:47.047 回答