【问题标题】:Reverse relationship in join table连接表中的反向关系
【发布时间】:2012-01-20 16:43:57
【问题描述】:

我有一个要为其编写查找的用户友谊模型

是一种称为 peers 的 habtm 关系,将 2 个用户联系在一起。关系是单个连接(Joe Steve,而不是 Joe -> Steve 和 Steve -> Joe)。

我的连接表如下: 用户身份 peer_id

两者都在关系中存储用户 ID。下面是用户的 HABTM。

has_and_belongs_to_many :peers, class_name: 'User', 
foreign_key: 'user_id', association_foreign_key: 'peer_id', 
join_table: 'users_peers'

我正在尝试找出允许连接表中的这条记录显示双方的查找器 sql。 user_id = 史蒂夫.id peer_id = joe.id

在我调用 joe.peers 和 steve.peers 时显示关系。目前,steve.peers 返回 joe,但 joe.peers 什么也没显示。

【问题讨论】:

标签: mysql ruby-on-rails database activerecord


【解决方案1】:

通常关系最好表示为单向关系,或一对单向关系。这是因为在大多数关系数据库中,很容易建立 A 到 B 或 B 到 A 关系,但不能同时使用一条记录。你基本上需要两个查询,除非你做了很多假设和修改。

根据我的经验,使用 has_and_belongs_to_many 不会让您的生活更轻松,因为它是 Rails 1.0 的遗留物,不如替换它的 has_many :through 方法好。在你的情况下,这就是结果:

class Node < ActiveRecord::Base
  has_many :peers_of,
    :class_name => 'Peer',
    :foreign_key => :of_user_id

  has_many :peers_to,
    :class_name => 'Peer',
    :foreign_key => :to_user_id

  has_many :peers,
    :through => :peers_of,
    :source => :to_user

  has_many :peers_with,
    :through => :peers_to,
    :source => :of_user
end

class Peer < ActiveRecord::Base
  belongs_to :of_user,
    :class_name => 'User'
  belongs_to :to_user,
    :class_name => 'User'
end

语义有点混乱,因此您可能需要调整它们。这里的想法是在添加“对等点”时建立双向关系,其中包含一对 A->B 和 B->A 记录。

出于查询的目的,您只需获取 @user.peers 之类的信息,而不必担心 peers_with 反向关系,因为如果您保持数据完整性,那么它应该会产生相同的结果。

【讨论】:

  • 谢谢,我会看看。我只是希望有一些魔力:) - 双向的自我参照关系让我有点受伤......
  • 编写一个任务来验证和修复其中一对丢失的关系比弄清楚如何将单向关系用作双向关系更容易。
【解决方案2】:

你可以手动写sql:

class PeerRelation
  belongs_to :user1, :class_name=>"User"
  belongs_to :user2, :class_name=>"User"
end

class User

  def set_peer(user)
     user1_id, user2_id = [self.id, user.id].sort
     PeerRelation.find_or_create_by_user1_id_and_user2_id(user1_id, user2_id)
  end

  def peers
    User.joins("inner join peer_relations on 
                  peer_relations.user1_id = #{self.id} or
                  peer_relations.user2_id = #{self.id}")

  end
end

但从数据完整性的角度来看,tadman 的方法更聪明,并且更符合 DBA 告诉您的内容。 (请参阅我对您问题的评论)

【讨论】:

  • 您也可以将其实现为关系上的finder_sql 定义,但是如果表很大,则在其中使用OR 进行JOIN 会使大多数数据库哭泣。
猜你喜欢
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多