【问题标题】:Ruby/DataMapper: Problems with multiple many-to-many associationsRuby/DataMapper:多个多对多关联的问题
【发布时间】:2013-05-07 06:48:54
【问题描述】:

我已经实现了用户-组关系模型,其中一个用户可以是一个或多个组的成员和所有者,而一个组可以有一个或多个所有者和一个或多个成员。

现在,问题是User.owned_groups 仅返回 1 个组,即使用户拥有超过 1 个组。

User.member_groupsGroup.ownersGroup.members 我也面临同样的问题。所有方法都只返回 1 条记录。

以下是数据库中的模型和值。

型号:-

require 'rubygems'
require 'data_mapper'
require 'dm-types'

module Contacts
  class User
    include DataMapper::Resource

    property :id,         Serial,   :key => true
    property :username,   String,   :required => true, :unique => true

    has n, :group_owners, :child_key => [:owned_group_id]
    has n, :owned_groups, 'Group', :through => :group_owners

    has n, :group_members, :child_key => [:member_group_id]
    has n, :member_groups, 'Group', :through => :group_members

    #------------------------------------------#
    # args should be an array of hashes        #
    # Example: args = [{:id => 1},{:id => 2}]  #
    #------------------------------------------#
    def self.get_users args
      users = Array.new
      args.each do |user|
        all_users = User.all(user)
        all_users.each do |u|
          user_hash = u.attributes

          user_hash[:owned_groups] = Array.new
          u.owned_groups.each do |owned_group|
            g = owned_group.attributes
            user_hash[:owned_groups].push g
          end

          user_hash[:member_groups] = Array.new
          u.member_groups.each do |member_group|
            g = member_group.attributes
            user_hash[:member_groups].push g
          end

          users.push user_hash
        end
      end
      return users
    end
  end

  class Group
    include DataMapper::Resource

    property :id,   Serial, :key => true
    property :name, String, :required => true, :unique => true

    has n, :group_owners, :child_key => [:owner_id]
    has n, :owners, 'User', :through => :group_owners

    has n, :group_members, :child_key => [:member_id]
    has n, :members, 'User', :through => :group_members

    #------------------------------------------#
    # args should be an array of hashes        #
    # Example: args = [{:id => 1},{:id => 2}]  #
    #------------------------------------------#
    def self.get_groups args
      groups = Array.new

      args.each do |group|
        all_groups = Group.all(group)
        all_groups.each do |g|
          group_hash = g.attributes

          group_hash[:owners] = Array.new
          g.owners.each do |owner|
            u = owner.attributes
            group_hash[:owners].push u
          end

          group_hash[:members] = Array.new
          g.members.each do |member|
            u = member.attributes
            group_hash[:members].push u
          end
          groups.push group_hash
        end
      end
      return groups
    end
  end

  class GroupOwner
    include DataMapper::Resource

    property :id, Serial, :key => true
    belongs_to :owner, 'User'
    belongs_to :owned_group, 'Group'
  end

  class GroupMember
    include DataMapper::Resource

    property :id, Serial, :key => true
    belongs_to :member, 'User'
    belongs_to :member_group, 'Group'
  end
end

MySQL:-

mysql> select * from contacts_users;
+----+-----------+
| id | username  |
+----+-----------+
|  1 | testuser1 |
|  2 | testuser2 |
+----+-----------+

mysql> select * from contacts_groups;
+----+------------+
| id | name       |
+----+------------+
|  1 | testgroup1 |
|  2 | testgroup2 |
+----+------------+
2 rows in set (0.00 sec)


mysql> select * from contacts_group_owners;
+----+----------+----------------+
| id | owner_id | owned_group_id |
+----+----------+----------------+
|  1 |        1 |              1 |
|  2 |        2 |              1 |
|  3 |        1 |              2 |
|  4 |        2 |              2 |
+----+----------+----------------+
4 rows in set (0.00 sec)

mysql> select * from contacts_group_members;
+----+-----------+-----------------+
| id | member_id | member_group_id |
+----+-----------+-----------------+
|  1 |         1 |               1 |
|  2 |         2 |               1 |
|  3 |         1 |               2 |
|  4 |         2 |               2 |
+----+-----------+-----------------+
4 rows in set (0.00 sec)

在调试模式下,这是为User.owned_groups生成的MySQL查询:

    SELECT 
      `contacts_groups`.`id`, 
      `contacts_groups`.`name`, 
      `contacts_groups`.`created_at`, 
      `contacts_groups`.`updated_at` 
   FROM `contacts_groups` 
   INNER JOIN `contacts_group_owners` 
      ON `contacts_groups`.`id` = `contacts_group_owners`.`owned_group_id` 
   INNER JOIN `contacts_users` 
      ON `contacts_group_owners`.`owned_group_id` = `contacts_users`.`id` 
   WHERE `contacts_group_owners`.`owned_group_id` = 1 
   GROUP BY 
      `contacts_groups`.`id`, 
      `contacts_groups`.`name`, 
      `contacts_groups`.`created_at`, 
      `contacts_groups`.`updated_at` 
   ORDER BY `contacts_groups`.`id

版本:

红宝石 - 2.0.0-p0

西纳特拉 - 1.3.4

DataMapper - 1.2.0

我错过了一些琐碎的事情吗?

提前致谢。

【问题讨论】:

  • 快速浏览并注意到您定义了child_keys,但没有定义关联的parent_keys。这可能不是问题,但我似乎记得通过这样做解决了我在 DM 上遇到的一些问题。当我有更多时间时,我会仔细看看并添加一个实际的答案,除非你当然已经弄清楚了......

标签: mysql ruby many-to-many sinatra datamapper


【解决方案1】:

试试这个:

   SELECT 
      *
   FROM 
      `contacts_groups` 
   INNER JOIN `contacts_group_owners` 
      ON `contacts_groups`.`id` = `contacts_group_owners`.`owned_group_id` 
   INNER JOIN `contacts_users` 
      ON `contacts_group_owners`.`owner_id` = `contacts_users`.`id` 
   WHERE 
      `contacts_group_owners`.`owned_group_id` = 1 

【讨论】:

  • 我正在使用 DataMapper,我不喜欢编写 mysql 查询。我想知道模型是否有问题。顺便说一句,输出应该是 testgroup1 和 testgroup2 但您的查询只返回 testgroup1。
  • @draxxxeus 我对 python 不太熟悉,所以我只是想看看我是否可以帮助您进行查询,是的,它只返回 testgroup1,因为您有条件 ``contacts_group_owners.owned_group_id` = 1` 但它也返回 testuser1 和 testuser2
  • 嗯,首先它是 ruby​​,其次,我还没有编写 MySQL 查询。 DataMapper 是一个生成查询的 ORM。无论如何,感谢您的努力。
  • 抱歉这个错误,如果该查询是由 ORM 生成的,那么肯定映射没有正确完成,很抱歉我无法为您提供更多帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2012-08-30
  • 2012-03-09
  • 1970-01-01
相关资源
最近更新 更多