RubyonRails:搜索一个表,其中多行必须存在于另一个表中
我试图创建一个搜索,其中一条记录必须在另一个表中有多条记录(通过id链接,并且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
有许多语句),才能作为结果包含在内
我有表用户
,技能列表
,技能地图
用户通过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])