在 Rails 中,如何在一个查找器中查询两个 has_many 关联?

Posted

技术标签:

【中文标题】在 Rails 中,如何在一个查找器中查询两个 has_many 关联?【英文标题】:In Rails, how do I query two has_many associations in a single finder? 【发布时间】:2022-01-20 16:13:58 【问题描述】:

我使用的是 Rails 4.2。我有以下带有几个 has_many 关联的用户模型

class User < ActiveRecord::Base
    …
  has_many :roles, through: :roles_users
  has_many :addresses, dependent: :destroy, as: :addressable, inverse_of: :addressable


class Role < ActiveRecord::Base

  has_and_belongs_to_many :users
  has_many :roles_users


class RolesUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :role

end


class Address < ActiveRecord::Base

  belongs_to :addressable, polymorphic: true
  alias :user :addressable

我想查找具有特定角色但没有任何地址的所有用户。我认为下面会做到这一点

> users = User.includes(:roles, :addresses).where(:roles => :name => 'User', :addresses => :user_id => nil)

但是当我检查结果时,我仍然得到有地址的结果……

2.7.1 :012 > users.last.addresses.count
…
 => 2

编写查询这两个 has_many 关联的查找器的正确方法是什么?

【问题讨论】:

您可以使用 NOT IN User.where.not(id: User.joins(:addresses, :roles).where(roles: name: 'admin' ).select(:id)) 对其进行测试。如果不能,您能否列出您在数据库中拥有的用户、角色、角色用户和地址?还将查询中涉及的每个模型中的关系添加到问题中。 谢谢大佬,帮我解决了。如果您想将该查询作为答案包含在内,我会接受。 【参考方案1】:

检查具有 nil 父 ID 的子记录就像在 Rails 4 中执行此操作的方式一样。但如果这不起作用,您可以使用 NOT IN 子句组合:

User
  .where
  .not(
    id: User
          .joins(:addresses, :roles)
          .where(roles:  name: 'User' )
          .select(:id)
  )

它基本上是通过用户 ID 过滤掉所有具有关联地址、具有角色且角色名称正是“用户”的用户行。你最终会得到这样的 SQL 查询:

SELECT "users".*
FROM "users"
WHERE "users"."id" NOT IN (
  SELECT "users"."id"
  FROM "users"
  INNER JOIN "roles_users" ON "roles_users"."user_id" = "users"."id"
  INNER JOIN "roles" ON "roles"."id" = "roles_users"."role_id"
  WHERE "roles"."name" = 'User'
)

【讨论】:

嘿,不想回溯我的评论,但是当我将您的查找方法保存到 var 时,“users”,然后运行“users.find|u| u.addresses.count > 0 ”,它返回一个结果。如果我正在查找没有与特定角色匹配的地址的用户,我希望我的查找不会返回任何内容。 不用担心。您可以在问题评论中添加我要求的信息吗? 谢谢。我添加了模型关系。我没有在数据库中添加单独的值,因为太多了,但是如果仍然需要这些值,让我尝试找出一种方法来提出仅与此示例相关的值。 确认,请忽略。一切都很好。我在 cmets (users.find|u| u.addresses.count > 0) 中的发现没有说明指定的角色。当我在混合中添加它时,结果确实是一致的。

以上是关于在 Rails 中,如何在一个查找器中查询两个 has_many 关联?的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 中,如何编写一个带有“where”的查找器来比较两个日期?

如何从两个不同的 Laravel 查询构建器中获取我的两个结果集以同时显示在同一页面上?

Rails / SQL 查询查找最近的事件

如何在 Rails 中使用查询进行简单连接

在 Laravel get() 查询构建器中附加两个数组

优化 Rails 急切加载查询以查找所有