【问题标题】:Class method problem with bidirectional self-referential associations具有双向自引用关联的类方法问题
【发布时间】:2011-06-09 06:39:54
【问题描述】:

我正在尝试创建一个应用程序,其中用户(“current_user”)评估其他两个用户(“user1”和“user2”)之间的兼容性。他们可以对兼容性进行正面或负面评价:给两个用户评分“兼容”会创建两个相同类别的资源(一个“positive_connection”和一个“inverse_positive_connection” - 用于双向性),并且给他们评分“不兼容”也会创建两个资源('negative_connection '和'inverse_negative_connection')。所以有positive_connection、negative_connection和user的模型。

每个评级资源都属于_创建它的用户,也属于它所连接的用户。拥有正面和负面的评级很重要。

这是我的问题:在每个用户 (@user) 页面上,我想显示单独的列表:

  1. overall_positively_connected_to(@user)(即positive_connections.count > negative_ratings.count)的用户,以及

  2. overall_negatively_connected_to(@user) 的用户(即negative_connections.count > positive_ratings.count)。


我似乎无法做的是编写一个 class 方法,该方法仅拉出那些净评级为“兼容”或“不兼容”的用户

通过阅读 Michael Hartl 的 rails 教程(我对这一切完全陌生),我认为我需要在 User 模型中编写类似这样的内容:

class User < ActiveRecord::Base


def self.that_are_compatible_with

     User.overall_positively_connected_to(user)
end
.
.
.


编辑

从完全不了解 SQL 查询开始,我编写了这两个类方法来查找与@user(分别)负连接和正连接的用户:

.
.
.
  def self.with_neg_connections_to(user)
   joins(:negative_connections).
   where(:negative_connections => {:user_a_id => user})
  end

  def self.with_pos_connections_to(user)
   joins(:positive_connections).
   where(:positive_connections => {:user_a_id => user})
  end


但这并没有多大帮助。我需要的是一种获取用户overall_positively_connected_to(user) 的方法。我认为该方法将涉及两个连接,然后是这样的:

  def self.overall_positively_connected_to(user)
    joins(:positive_connections).joins(:negative_connections).
    where((:negative_connections => {:user_a_id => user}).count > (:positive_connections => {:user_a_id => user}).count)
  end


但是在这里我完全卡住了:这显然是不对的。我在任何地方都找不到其他类似的例子......

在这方面的任何帮助都会很棒,因为我对 SQL 查询一无所知。如果需要更多代码,请告诉我。提前致谢!

【问题讨论】:

    标签: sql ruby-on-rails ruby-on-rails-3 bidirectional self-reference


    【解决方案1】:

    在为此苦苦挣扎了几天后,我决定解决问题的最佳方法可能是更改模型轮次 - 通过添加额外的“连接”模型并让用户对每个模型进行正面或负面投票连接,或者通过精简到单个“连接”模型,其中每个连接的正或负字符由 +1/-1 标​​记。

    this question 的回答中可以找到一些替代方案。

    【讨论】:

      【解决方案2】:

      如果我正确理解了问题,那么使这一切变得复杂的原因之一是目标用户可能位于 User1 或 User2 中。也就是说,如果我们毕竟是 ID=4 的 User 的所有连接,那么我们可以有 User1 = 4 或 User2 = 4... 对吗?

      如果是这样,那么假设您的 positive_connections 和negative_connections 模型/表具有如下字段:

      • ID:主键
      • ReportingUser:建立连接的用户
      • UserA:第一个连接的用户
      • UserB:第二个要连接的用户

      然后下面的(相当混乱的)SQL 将为您提供每个用户的正负连接的摘要:

      set @user = 2;
      
      SELECT DISTINCT
          @user TargetUser,
          u.ID as OtherUser,
          COALESCE(qryPositive.PositiveConnections, 0) as PositiveConnections,
          COALESCE(qryNegative.NegativeConnections, 0) as NegativeConnections,
          case
            when COALESCE(qryPositive.PositiveConnections, 0) > COALESCE(qryNegative.NegativeConnections, 0)
            then 'positive'
            when COALESCE(qryPositive.PositiveConnections, 0) < COALESCE(qryNegative.NegativeConnections, 0)
            then 'negative'
            else 'neutral'
          end as Status
      FROM
          users u
      LEFT JOIN
          (
              -- The number of positive connections between the @user and each other user
              SELECT
                  @user TargetUser,
                  a.OtherUser,
                  COUNT(*) as PositiveConnections
              FROM
              (
                  -- The positive_connections rows with our @user in it
                  -- and the other user that the connection associates them with
                  select -- pc.ID as pcID, pc.UserA, pc.UserB,
                  case
                    when pc.UserA = @user then pc.UserB
                    else pc.UserA
                  end as OtherUser
                  from positive_connections pc
                  where
                  (
                    -- Check both columns
                    (pc.UserA = @user)
                    or
                    (pc.UserB = @user)
                  )
              ) a
              GROUP BY
                  OtherUser
          ) qryPositive
          on qryPositive.OtherUser = u.ID
      
      LEFT JOIN
          (
              -- The number of negative connections between the @user and each other user
              SELECT
                  @user TargetUser,
                  b.OtherUser,
                  COUNT(*) as NegativeConnections
              FROM
              (
                  -- The negative_connections rows with our @user in it
                  -- and the other user that the connection associates them with
                  select -- pc.ID as pcID, pc.UserA, pc.UserB,
                  case
                    when pc.UserA = @user then pc.UserB
                    else pc.UserA
                  end as OtherUser
                  from negative_connections pc
                  where
                  (
                    -- Check both columns
                    (pc.UserA = @user)
                    or
                    (pc.UserB = @user)
                  )
              ) b
              GROUP BY
                  OtherUser
          ) qryNegative
          on qryNegative.OtherUser = u.ID
      
      WHERE
          u.ID <> @user
      

      这会处理 SQL(如果您愿意,我可以发布我使用的示例数据)。现在在 Rails 中,将其分离到模型中的单独类方法中绝对是一个好主意,就像您已经开始做的那样。

      就使用 Rails 构建查询而言,此页面是一个很好的资源。 http://guides.rubyonrails.org/active_record_querying.html

      这是您正在寻找的东西吗?如果是这样,那么我们可以构建活动记录查询。 (我感觉我可能误解了这个问题......)

      【讨论】:

      • 感谢您的回复。这不是我的意思,但是让数据库结构过于复杂是我的错。我实际上想从数据库中提取那些与任何给定用户(@user)有更多积极而不是消极联系的用户。最后我通过改变我的模型解决了这个问题。我会尽快发布我的解决方案作为答案。无论如何,再次感谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 2015-05-31
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      相关资源
      最近更新 更多