查询关联数据时预先加载关联

Eager load associations when querying against association data

我有一个模型 "User",它与另一个模型 "Membership" 具有一对多关系。成员资格有一个名为 "group" 的字段,其中包含一个组的名称。我想查询特定 "group" 中的所有用户记录,并为每个返回的用户预加载所有 "memberships"。

在我进一步讨论之前,我知道通常您会实施 "Group" 模型并使 Membership 成为用户和组之间的联接 table,然后只查询特定组的所有用户。这个例子有点做作,但它代表了我正在处理的真实案例。

无论如何,我尝试了以下查询:

User.includes(:memberships).where(memberships: { group: groupname })

但是,虽然此 returns 是正确的用户,但它只会急切加载与查询匹配的成员资格。换句话说,如果用户 "Bob" 在 "red" 和 "blue" 组中,并且我查询所有 "blue" 组用户,则用户 "Bob" 是在结果中返回,但只加载了他的 "blue" 组成员资格。

有没有办法通过单个数据库查询来执行此操作并预先加载每个返回用户的所有成员资格?

在您的示例中,执行单个数据库查询是因为关联有查询条件。通常,includes 会执行两个数据库查询,一个用于加载用户,另一个用于加载关联的成员资格。

我注意到了这一点,因为有一个解决方案可以执行两个数据库查询并且很好(默认的 ActiveRecord 预加载行为)

User.preload(:memberships).joins(:memberships).where(memberships: {group: groupname})

注意:示例中使用了preload方法而不是includes。这是为了仅在第一个查询中应用关联 table 的查询条件,而不影响预加载 memberships 的第二个查询。默认情况下,当关联 table 上没有额外的查询条件时,include 的工作方式类似于 preload.

第一个查询将获取所有具有所需组成员资格的用户。

第二个查询将在没有任何额外条件的情况下获取所有关联的成员资格。