简体   繁体   English

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

[英]Compare associations between domain objects in Grails

I am not sure if I am going about this the best way, but I will try to explain what I am trying to do. 我不确定是否要采用最佳方法,但是我将尽力解释我要做什么。

I have the following domain classes 我有以下领域课程

class User { static hasMany = [goals: Goal] } 类User {static hasMany = [目标:目标]}

So each User has a list of Goal objects. 因此,每个用户都有一个目标对象列表。 I want to be able to take an instance of User and return 5 Users with the highest number of matching Goal objects (with the instance) in their goals list. 我希望能够获得一个User实例,并在其目标列表中返回5个用户(具有该实例)的匹配Goal对象数量最多。

Can someone kindly explain how I might go about doing this? 有人可以请我解释一下我该怎么做吗?

The easiest and most efficient way to achieve this is using plain SQL. 实现此目的的最简单,最有效的方法是使用普通SQL。 Assuming you have these tables 假设您有这些表

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

You can have the following query to do what you need: 您可以使用以下查询执行所需的操作:

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;

This takes a user id and returns a list of other users with matching goals, sorted by the number of matches. 这将获取一个用户ID,并返回具有匹配目标的其他用户的列表,并按匹配次数排序。 Wrap it up in a GoalService and you're done! 将其包装在GoalService ,您就完成了!

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

It may also be possible to do this with criteria or HQL, but with queries like this it's usually easier to use SQL. 也可以使用条件或HQL来执行此操作,但是使用此类查询通常更容易使用SQL。

If you're looking for a simple match, perhaps the easiest way would be to do a findAll for each Goal and then count the number of results that each other User appears in: 如果您正在寻找简单的匹配项,那么最简单的方法可能是对每个目标进行一次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]

This may be too slow, depending on your needs, but it is simple. 根据您的需要,这可能太慢,但是很简单。 If many users share the same goals then you could cache the results of findAllByGoal. 如果许多用户共享相同的目标,则可以缓存findAllByGoal的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM