我有一个相当复杂的查询我试图在Rails中做,我不完全确定如何希望有人可以提供帮助。
我有两个型号,User和Place。
用户与Place两次相关。一次为visited_places,一次为planned_places。它有很多很多关系但是使用has_many:through。这是User的关系。
has_many :visited_places
has_many :visited, :class_name=>"Place", :through=>:visited_places, :source=>:place
has_many :planned_places
has_many :planned, :class_name=>"Place", :through=>:planned_places, :source=>:place
就地定义了这种关系。这是那里的定义
has_many :visited_users, :class_name=>"User", :through=>:visited_places
has_many :planned_users, :class_name=>"User", :through=>:planned_places
我正在尝试在Place上写一个find,它返回数据库中与访问者或计划用户无关的所有地方。现在我通过简单地查询所有地方然后从结果中减去访问和计划来完成这个,但我想加入分页,我担心这可能会使之复杂化。这是我目前的代码。
all_places = Place.find(:all)
all_places = all_places - user.visited - user.planned
任何人都知道如何通过调用Place.find来实现这一目标。这也是一个Rails 3应用程序,所以如果任何有效的记录改进使这更容易,他们是一个选项。
答案 0 :(得分:2)
如下:
unvisited_places = Place.find(:all, :conditions => "id NOT IN(#{visited_places.map(&:place_id)})")
这是一般性的想法 - 根据您的最终需求,它可以更高效,更方便。
答案 1 :(得分:0)
您没有显示它,但如果我认为VisitedPlace
和PlannedPlace
模型具有belongs_to :user
关系,那么这些表具有user_id
辅助密钥,对吗?
因此,在这种情况下,我认为在数据库中执行此操作是最有效的,在这种情况下,您正在寻找places
,visited_places
和{{1}的表连接中的选择其中planned_places
或users.id
visited_places
的地方
答案 2 :(得分:0)
在sql中:
select * from places where id not in
(
(select place_id from visited_places where user_id = ?)
union
(select place_id from planned_places where user_id=?)
)
如果该查询有效,您可以按如下方式使用:
Places.find_by_sql(...the complete sql query ...)
我不知道如何在Rails 3中编写这样的查询,否则就是这样。
答案 3 :(得分:0)
我最近遇到了类似的愿望......我希望得到所有与Model2无关的Model1。使用Rails 4.1,这就是我所做的:
Model1.where.not(id: Model2.select(:user_id).uniq)
这会创建一个嵌套的SELECT,就像@nathanvda建议的那样,有效地让数据库完成所有工作。生成的示例SQL是:
SELECT "model1s".* FROM "model1s" WHERE ("model1s"."id" NOT IN (SELECT DISTINCT "model2s"."model1_id" FROM "model2s"))