比较Grails中域对象之间的关联

时间:2010-04-08 00:30:46

标签: grails groovy

我不确定我是否会以最好的方式解决这个问题,但我会尝试解释我想要做的事情。

我有以下域类

类用户{    static hasMany = [目标:目标] }

因此每个用户都有一个Goal对象列表。我希望能够获取一个User实例,并在目标列表中返回具有最多匹配目标对象(带有实例)的5个用户。

有人可以解释一下我可能会这样做吗?

2 个答案:

答案 0 :(得分:0)

实现此目的的最简单,最有效的方法是使用纯SQL。假设你有这些表

users      [id]
goals      [id, description]
user_goals [user_id, goal_id]

您可以使用以下查询来执行所需操作:

set @userId=123;
select user_id, count(*) as matched from user_goals
where user_id!=@userId
  and goal_id in (select ug.goal_id from user_goals ug where ug.user_id=@userId)
group by user_id order by matched desc limit 5;

这将获取用户ID并返回具有匹配目标的其他用户的列表,按匹配数排序。将其包裹在GoalService中,您就完成了!

class GoalService {
  def findUsersWithSimilarGoals(user) {
    // ...
  }
}

也可以使用条件或HQL来执行此操作,但对于这样的查询,通常更容易使用SQL。

答案 1 :(得分:0)

如果你正在寻找一个简单的匹配,也许最简单的方法是为每个目标做一个findAll,然后计算每个其他用户出现的结果数量:

Map user2Count = [:]
for (goal in myUser.goals){
    for (u in User.findAllByGoal(goal)){
         def count = user2Count.containsKey(u) ? user2Count.get(u) : 0
         count++
         user2Count.put(u, count)
    }
}
// get the top 5 users
def topUsers = user2Count.entrySet().sort({ it.value }).reverse()[0..5]

根据您的需要,这可能太慢,但很简单。如果许多用户共享相同的目标,那么您可以缓存findAllByGoal的结果。