在自联接中的两个外键之间搜索的查询 table
query to search between two foreign keys in a self join table
用户中的示例数据 table
rails 控制台中的预期结果,father.children
和 mother.children
应该 return 同一组对象:
father = User.first
father.children
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "son", father_id: 1, mother_id: 2>, #<User id: 4, name: "daughter", father_id: 1, mother_id: 2>]>
mother = User.find(2)
mother.children
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "son", father_id: 1, mother_id: 2>, #<User id: 4, name: "daughter", father_id: 1, mother_id: 2>]>
这是我现在在 User.rb 模型中的协会。它 return 是我执行 father.children
的预期结果,因为 foreign_key 指的是 father_id
。但它不适用于 mother.children
因为它不引用 mother_id
.
has_many :children, foreign_key: "father_id", class_name: "User"
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
我有办法吗
foreign key: "father_id" OR "mother_id"
我也尝试在协会中进行查询,但似乎无法理解它。
has_many :children, -> { where("father_id = id OR mother_id = id") }, class_name: "User"
您可以取消该查询创建的默认范围,然后使用用户 ID 过滤子行:
has_many :children,
->(user) { unscope(:where).where('father_id = :id OR mother_id = :id', id: user.id) },
class_name: "User"
为什么unscope
?如果不删除它,您的代码将导致两个 SQL 查询,如下所示:
SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
SELECT "users".* FROM "users" WHERE "users"."user_id" = ? AND "users"."father_id" = ? [["user_id", 1], ["father_id", "1"]]
做 User.first.children
时 - 至少在 Rails 6.1.4.
如您所见,第二个查询过滤了所有 id
等于接收者 (1) 且同时具有 father_id
列等于接收者 (1) 的用户.查看您的代码,这可能永远不会发生。
注意,如果在声明 has_many
关系后您真的不需要将所有这些方法添加到模型中,您最好使用单个实例方法或作用域(在最后一种情况下) .因为使用这种方法,您覆盖了默认行为(无处记录),即通过此行中的主键过滤其他 table 中的行。
用户中的示例数据 table
rails 控制台中的预期结果,father.children
和 mother.children
应该 return 同一组对象:
father = User.first
father.children
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "son", father_id: 1, mother_id: 2>, #<User id: 4, name: "daughter", father_id: 1, mother_id: 2>]>
mother = User.find(2)
mother.children
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "son", father_id: 1, mother_id: 2>, #<User id: 4, name: "daughter", father_id: 1, mother_id: 2>]>
这是我现在在 User.rb 模型中的协会。它 return 是我执行 father.children
的预期结果,因为 foreign_key 指的是 father_id
。但它不适用于 mother.children
因为它不引用 mother_id
.
has_many :children, foreign_key: "father_id", class_name: "User"
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
我有办法吗
foreign key: "father_id" OR "mother_id"
我也尝试在协会中进行查询,但似乎无法理解它。
has_many :children, -> { where("father_id = id OR mother_id = id") }, class_name: "User"
您可以取消该查询创建的默认范围,然后使用用户 ID 过滤子行:
has_many :children,
->(user) { unscope(:where).where('father_id = :id OR mother_id = :id', id: user.id) },
class_name: "User"
为什么unscope
?如果不删除它,您的代码将导致两个 SQL 查询,如下所示:
SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
SELECT "users".* FROM "users" WHERE "users"."user_id" = ? AND "users"."father_id" = ? [["user_id", 1], ["father_id", "1"]]
做 User.first.children
时 - 至少在 Rails 6.1.4.
如您所见,第二个查询过滤了所有 id
等于接收者 (1) 且同时具有 father_id
列等于接收者 (1) 的用户.查看您的代码,这可能永远不会发生。
注意,如果在声明 has_many
关系后您真的不需要将所有这些方法添加到模型中,您最好使用单个实例方法或作用域(在最后一种情况下) .因为使用这种方法,您覆盖了默认行为(无处记录),即通过此行中的主键过滤其他 table 中的行。