提问人:Sonfaya 提问时间:10/27/2023 更新时间:10/27/2023 访问量:42
查询包含 related_model 的模型的数据库,其中相关模型有 2 个特定 ID
Query db for a model including related_model, where related model have 2 specific ids
问:
在 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使用。
有没有一种干净的方法可以做到这一点,而不必在查询房间后循环访问房间?
答:
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 时会抱怨,而没有在部件中定义它。您可以尝试删除该行。
COUNT
select
COUNT
having
select
- 在两个表之间执行 a。
join
INNER JOIN
- 这是你已经拥有的想要。
where
- 将找到的记录分组为一行,并允许使用 .
group
COUNT
- 唯一返回至少关联的那些。
having
rooms
user_ids.size
users_rooms
评论
0赞
max
10/27/2023
除非您为其分配别名,否则选择计数实际上并没有用处。
0赞
Sonfaya
10/27/2023
这正是我想要的,谢谢你的笔记。我将帖子设置为解决,但我心中还有另一个问题(不是有用的自动取款机,但我想可能是以后),我试图修改它以仅包含完全关联的房间。我只是将 having 方法更改为:但它仍然返回更多房间,我错过了什么吗?user_ids.size
users_rooms
having('COUNT(users_rooms.user_id) = ?', user_ids.size)
user_ids.size
having
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))
创建间接关联是可选的,但抽象使它使查询不受联接表实现方式的约束。
例如,它不是一个好名字,你可能想称它为更合适的名字——这样你就可以在不破坏任何东西的情况下做到这一点。UsersRoom
Booking
评论
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
上一个:按包含字母和数字的属性排序
下一个:基于列值的自定义has_one
评论