如何使用Mongoid按嵌套字段值排序?

时间:2013-05-09 00:04:04

标签: ruby sorting mongoid mongoid3 database-relations

假设我有User字段为name,其中has_many teamsTeam属于user,且属于a sportSport有一个字段name和has_many teams

我想浏览sports,做一些事情,并收集按teams的{​​{1}}排序的name数组。

user

这样运行但是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按关系的值对集合进行排序的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

我认为没有办法用Mongoid做到这一点。如果您排序的字段是嵌入式文档的一部分,则可能有效,但在这种情况下,您使用的是引用文档。

我猜你在这里可能有两个选择,那就是用红宝石排序团队集合的效率较低:

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

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

相关问题