查询包含 related_model 的模型的数据库,其中相关模型有 2 个特定 ID

Query db for a model including related_model, where related model have 2 specific ids

提问人:Sonfaya 提问时间:10/27/2023 更新时间:10/27/2023 访问量:42

问:

在 rails 应用程序中,我有 3 个模型,Room、User 和 UsersRoom,它们是 Room 和 User 之间的关联表。 我想查询与多个用户相关的聊天室。

如果我这样做:

Room.includes(:users_rooms).where(users_rooms: { user_id: user_ids }

我得到所有房间,至少有一个users_room包含一个users_ids。 我想让房间里有users_rooms礼物供user_ids使用。

有没有一种干净的方法可以做到这一点,而不必在查询房间后循环访问房间?

Ruby-on-Rails Ruby PostgreSQL ActiveRecord

评论


答:

1赞 spickermann 10/27/2023 #1

我会尝试以下方法:

Room
  .select('rooms.*, COUNT(users_rooms.user_id)')
  .joins(:users_rooms)
  .where(users_rooms: { user_id: user_ids })
  .group('rooms.id')
  .having('COUNT(users_rooms.user_id) >= ?', user_ids.size)

笔记:

  • in 是必需的,因为某些数据库引擎版本在使用 in 时会抱怨,而没有在部件中定义它。您可以尝试删除该行。COUNTselectCOUNThavingselect
  • 在两个表之间执行 a。joinINNER JOIN
  • 这是你已经拥有的想要。where
  • 将找到的记录分组为一行,并允许使用 .groupCOUNT
  • 唯一返回至少关联的那些。havingroomsuser_ids.sizeusers_rooms

评论

0赞 max 10/27/2023
除非您为其分配别名,否则选择计数实际上并没有用处。
0赞 Sonfaya 10/27/2023
这正是我想要的,谢谢你的笔记。我将帖子设置为解决,但我心中还有另一个问题(不是有用的自动取款机,但我想可能是以后),我试图修改它以仅包含完全关联的房间。我只是将 having 方法更改为:但它仍然返回更多房间,我错过了什么吗?user_ids.sizeusers_roomshaving('COUNT(users_rooms.user_id) = ?', user_ids.size)user_ids.sizehaving
0赞 max 10/27/2023 #2

我会做:

class Room
  # ...
  has_many :users, though: :users_rooms
end
Room.group(:id)
    .joins(:users)
    .where(users: { id: user_ids })
    .having(User.arel_table[:id].count.gte(user_ids.size))

创建间接关联是可选的,但抽象使它使查询不受联接表实现方式的约束。

例如,它不是一个好名字,你可能想称它为更合适的名字——这样你就可以在不破坏任何东西的情况下做到这一点。UsersRoomBooking

评论

0赞 Sonfaya 10/27/2023
这看起来很酷,我需要对这里发生的事情进行一些投资,看看执行了什么 SQL 以将其与 Spikkerman 响应进行比较。是的,我可能应该重命名它。
0赞 max 10/27/2023
基本方法与 spickermann 的答案非常相似,只是条件是在 users 表而不是 join 表上设置的,并且使用 Arel 而不是 SQL 字符串。 创建。.having(User.arel_table[:id].count.gte(user_ids.size))HAVING COUNT("users"."id") >= x