RubyonRails:搜索一个表,其中多行必须存在于另一个表中

RubyonRails:搜索一个表,其中多行必须存在于另一个表中,ruby,ruby-on-rails-3,search,multiple-conditions,Ruby,Ruby On Rails 3,Search,Multiple Conditions,我试图创建一个搜索,其中一条记录必须在另一个表中有多条记录(通过id链接,并且有许多语句),才能作为结果包含在内 我有表用户,技能列表,技能地图 用户通过skill\u maps表中的单个条目映射到个人技能。许多用户可以共享单个技能,单个用户可以通过skill\u maps表中的多个条目拥有多个技能 e、 g 用户2拥有技能9和15 用户3只有技能9 我正在尝试创建一个搜索,返回所有具有一组技能的用户的哈希值。所需的技能ID集在参数中显示为数组 以下是我正在使用的代码: skill_select

我试图创建一个搜索,其中一条记录必须在另一个表中有多条记录(通过id链接,并且
有许多
语句),才能作为结果包含在内

我有表
用户
技能列表
技能地图

用户通过
skill\u maps
表中的单个条目映射到个人技能。许多用户可以共享单个技能,单个用户可以通过
skill\u maps
表中的多个条目拥有多个技能

e、 g

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

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

以下是我正在使用的代码:

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})
问题是,这会返回所有拥有这些技能的用户,而不是所有拥有这些技能的用户

另外,我的用户表链接到技能列表表
:到=>:技能映射
,反之亦然,这样我就可以调用
@user.skill\u list


我确信这是一个真正的新手问题,我对rails(和编程)是完全陌生的。我找了又找,但什么也找不到。我真的不知道如何用一个搜索词来解释这个问题。

我个人不知道如何使用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,并让DB引擎来完成这项工作。如果您需要高性能,我可能会为您提供一些SQL。(如果其他人可以,请编辑此答案!)


顺便说一句,您可能应该在
skill\u maps.skill\u list\u id
上放置一个索引,以确保即使
skill\u maps
表变得非常大,也能获得良好的性能。请参阅ActiveMigration文档:

您可能需要使用一些自定义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中使用
findby\uSQL
执行此操作:

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])

如果表名和列名不完全正确,很抱歉,但希望这是大致正确的。

有效!!非常感谢你!在我可以通过这个新列表搜索我的users表之前,我必须在a中添加一个。这是我最后的代码:
skill\u selection\u user\u id=params[:teach\u skill\u id].map{124; s|Set.new(SkillMap.find\u all\u by\u skill\u list\u id.map(&:user\u id)).reduce(:&@results=user.find(:all,:conditions=>{id=>skill selection\u user\u id.to\u a})
再次感谢!!!您可以这样做:
@results=User.find skill\u selection\u User\u id.entries
'“条目”将集合转换为一个数组,您只需将其馈送到“查找”即可。
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])