【问题标题】:How to find all items not related to another model - Rails 3如何查找与另一个模型无关的所有项目 - Rails 3
【发布时间】:2010-07-13 19:42:04
【问题描述】:

我尝试在 Rails 中进行相当复杂的查找,但我不完全确定希望有人能提供帮助。

我有两个模型,用户和地点。

一个用户与 Place 关联了两次。一次用于visited_places,一次用于planned_places。它是多对多关系,但使用 has_many :through。这是来自用户的关系。

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 上编写一个查找,该查找返回数据库中通过已访问或计划返回与用户无关的所有位置。现在我通过简单地查询所有地点然后从结果中减去访问和计划来完成此操作,但我想添加分页,我担心这会使情况复杂化。这是我当前的代码。

all_places = Place.find(:all)        
all_places = all_places - user.visited - user.planned

任何人都知道我如何通过调用 Place.find 来完成此操作。这也是一个 Rails 3 应用程序,因此如果任何活动记录改进使这更容易,它们是一个选项。

【问题讨论】:

  • OT,但您可能想要重命名您的连接模型 -- 似乎您的 :visited_places 连接模型应该重命名为“PlaceVisits”,然后您可以拥有 has_many :place_visitshas_many :visited_places, :through=>:place_visits跨度>

标签: ruby-on-rails ruby-on-rails-3


【解决方案1】:

怎么样:

unvisited_places = Place.find(:all, :conditions => "id NOT IN(#{visited_places.map(&:place_id)})")

这是一般的想法——它可以根据您的最终需求变得更加高效和方便。

【讨论】:

  • 通常这会起作用,但要创建 id 的列表,使用 visited_places.map 如您所写,rails 必须首先查询所有visited_places。最好在 1 次查询中做到这一点。让数据库为您完成这项工作。
【解决方案2】:

您没有显示它,但如果我正确地假设 VisitedPlacePlannedPlace 模型具有 belongs_to :user 关系,那么这些表具有 user_id 辅助键,对吗?

所以在这种情况下,我认为在数据库中执行此操作是最有效的,在这种情况下,您正在寻找跨表连接 placesvisited_placesplanned_places 的选择 users.id不在visited_placesplanned_places 中的任何一个中

【讨论】:

    【解决方案3】:

    在 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 中编写这样一个带有排除项的查询。

    【讨论】:

      【解决方案4】:

      我最近遇到了类似的愿望...我想获得所有与 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"))
      

      【讨论】:

        猜你喜欢
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多