0

我有这些(简化的)模型:

Address
public (Boolean)
has_one :group_member

Group
has_many :Group_Members
belongs_to :User

Group_Member
belongs_to :group
belongs_to :address

User
has_many :groups

我想选择所有public正确的地址以及用户可以通过组访问的所有地址。

我认为它是这样的:

Address.where(public: TRUE).joins(:group_member)

我在附近吗?

如果对任何人有帮助,我将使用 Rails 4 和 PostgreSQL 作为我的数据库。

4

2 回答 2

1

我认为这会起作用:

Address.joins(group_member: :group).where(is_public: true, groups: {user_id: 12345})

让我们分解一下。

首先我们调用Address模型,b/c 这就是我们想要返回的。

.joins(:group_member)group_members通过Address has_one :group_member关系加入地址。

但是,我们实际上想更进一步,将连接的group连接与 连接group_member,所以我们使用嵌套连接,这就是为什么看起来像这样joins(group_member: :group)表示我们连接地址 -> 组成员,然后组成员 -> 组。

接下来是 where 子句。有两个条件,我们想要:

  1. 仅限公共地址,在地址上显示为一列,因此我们添加以下内容: .where(is_public: true).
  2. 我们只需要特定用户与组连接的位置(以及它的 group_members 和地址)。为此,我们需要添加一个嵌套的 where 子句,就像这样groups: {user_id: 12345}

结合这些的结果是:

where(is_public: true, groups: {user_id: 12345})

所以总的来说,上面的代码行应该得到你想要的。

于 2013-09-30T22:22:12.803 回答
1

试试下面的——它不是一个单一的查询,但我认为它比一个带有大连接表的单一查询要好:

public_addresses = Address.where(is_public: true)
# =>  get all public addresses

user_addresses = current_user.groups.includes(:group_members => :address).
                # includes is to eager load records to avoid N+1 queries
                flat_map{|g| g.group_members.map(&:address)}
                # inner block returns array of addresses for each group
                # flat_map converts the array of arrays to single level 
# => get all addresses associated with the user


all_addresses = (public_addresses + user_addresses).uniq
# =>  remove duplicates

为了加快查询速度,为较慢的查询添加索引。例如

   add_index :groups, :user_id
   # this speeds up finding groups for a given user

   add_index :group_members, :group_id
   # this speeds up finding group_members for a given group

   add_index :addresses, :group_member_id
   # this speeds up finding addresses for a given group_member

其他选项是user_addresses使用join表格

   user_addresses = Address.joins(group_member: group).where(groups: {user_id: current_user.id} )
于 2013-09-30T22:37:13.833 回答