1

我正在尝试创建一个搜索,其中单个记录必须在另一个表中包含多个记录(由 id 和has_many语句链接)才能包含在结果中。

我有桌子users,,,skill_listsskill_maps

用户通过表中的单个条目映射到个人技能skill_maps。许多用户可以共享一个技能,单个用户可以通过表格中的多个条目拥有许多技能skill_maps

例如

User_id | Skill_list_id
2       | 9
2       | 15
3       | 9

用户 2 有技能 9 和 15
用户 3 只有技能 9

我正在尝试创建一个搜索,该搜索返回具有一组技能的所有用户的哈希值。所需的集合skill_ids在参数中显示为数组。

这是我正在使用的代码:

skill_selection_user_ids = SkillMap.find_all_by_skill_list_id(params[:skill_ids]).map(&:user_id) 

@results = User.find(:all, :conditions => {:id => skill_selection_user_ids})

问题是这会返回所有拥有这些技能的所有用户,而不是拥有所有这些技能的用户。

此外,我的用户表链接到技能列表表:through => :skill_maps,反之亦然,这样我就可以调用@user.skill_list等...

我确定这是一个真正的新手问题,我对 Rails(和编程)完全陌生。我搜索并寻找解决方案,但找不到任何东西。我真的不知道如何用一个搜索词来解释这个问题。

4

2 回答 2

1

我个人不知道如何使用 ActiveRecord 的查询接口来做到这一点。最简单的做法是检索具有每个单独技能的用户列表,然后获取这些列表的交集,可能使用 Set:

require 'set'

skills = [5, 10, 19] # for example
user_ids = skills.map { |s| Set.new(SkillMap.find_all_by_skill_list_id(s).map(&:user_id)) }.reduce(:&)
users = User.where(:id => user_ids.to_a)

为了(可能)更高的性能,您可以“滚动您自己的”SQL 并让数据库引擎完成工作。如果您在这里需要高性能,我可能会为您提供一些 SQL。(或者如果其他人可以,请编辑此答案!)

skill_maps.skill_list_id顺便说一句,即使skill_maps表变得非常大,您也应该放置一个索引以确保良好的性能。请参阅 ActiveMigration 文档:http ://api.rubyonrails.org/classes/ActiveRecord/Migration.html

于 2012-02-10T21:19:41.627 回答
1

您可能必须使用一些自定义 SQL 来获取用户 ID。我在类似的 HABTM 关系上测试了这个查询,它似乎有效:

SELECT DISTINCT(user_id) FROM skill_maps AS t1 WHERE (SELECT COUNT(skill_list_id) FROM skill_maps AS t2 WHERE t2.user_id = t1.user_id AND t2.skill_list_id IN (1,2,3)) = 3

诀窍在于子查询。对于外部查询中的每一行,它会查找与您感兴趣的任何技能匹配的该行的记录计数。然后它检查该计数是否与您感兴趣的技能总数匹配。如果有匹配,则用户必须具备您搜索的所有技能。

您可以使用以下命令在 Rails 中执行此操作find_by_sql

sql = 'SELECT DISTINCT(user_id) FROM skill_maps AS t1 WHERE (SELECT COUNT(skill_list_id) FROM skill_maps AS t2 WHERE t2.user_id = t1.user_id AND t2.skill_list_id IN (?)) = ?'
skill_ids = params[:skill_ids]
user_ids = SkillMap.find_by_sql([sql, skill_ids, skill_ids.size])

抱歉,如果表名和列名不完全正确,但希望这是在球场上。

于 2012-02-10T22:23:58.223 回答