假设我有User
字段为name
,其中has_many teams
和Team
属于user
,且属于a sport
。 Sport
有一个字段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
按关系的值对集合进行排序的正确方法是什么?
答案 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
鉴于维护起来并不是非常简单,这可能是使用观察者而不是回调的好人选,但你明白了。