Ruby on rails 活动记录。包括where子句

Ruby on rails 活动记录。包括where子句,ruby-on-rails,Ruby On Rails,我试图通过使用includes来避免N+1查询,但我需要过滤掉一些子记录。以下是我目前掌握的情况: Column.includes(:tickets).where(board_id: 1, tickets: {sprint_id: 10}) 问题是只返回包含sprint_id为10的票证的列。我想返回board_id为1的所有列,并且只预取sprint_id为10的票证,因此column.tickets要么是sprint_id为10的票证对象列表的空列表。column.includes:tic

我试图通过使用includes来避免N+1查询,但我需要过滤掉一些子记录。以下是我目前掌握的情况:

Column.includes(:tickets).where(board_id: 1, tickets: {sprint_id: 10})
问题是只返回包含sprint_id为10的票证的列。我想返回board_id为1的所有列,并且只预取sprint_id为10的票证,因此column.tickets要么是sprint_id为10的票证对象列表的空列表。

column.includes:tickets.where board_id:1,票证:{sprint_id:10}进行两次SQL查询。一个用于选择与指定where子句匹配的列,另一个用于选择并加载其列id等于匹配列id的票证

要在不加载不需要的票证的情况下获取所有相关列,可以执行以下操作:

columns=Column.whereboard\u id:1.to\u a tickets=Ticket.wherecolumn\u id:columns.map&:id,sprint\u id:10.to\u a 这样,您将无法调用每个列上的票证,因为它将再次进行数据库查询,您将遇到N+1问题,但要使用类似的方式访问列的票证而不进行任何查询,您可以执行以下操作:

分组\u票证=票证。分组依据&:列\u id 列。每个do |列| column\u tickets=分组的\u tickets[column.id] 如果有专栏的票,就处理一下吧。 终止
这就是include的工作原理。添加where子句时,它将应用于整个查询,而不仅仅是加载关联的记录

一种方法是向后翻转查询:

columns = Ticket.eager_load(:columns)
                .where(sprint_id: 10, columns: { board_id: 1 })
                .map(&:column)
                .uniq

在一条语句中实现您想要的东西是没有意义的。至少对我来说。我会这样做,首先,从where语句中删除票据。第二,当您调用column.tickets时,在末尾添加。wheresprint\u id:10。除此之外,我可能会编写一个自定义sql.Gotcha。问题是,这会创建一个N+1查询,其中N是列数,否?如果是,请尝试添加Column.all?不要相信这些查询会导致N+1:@columns=Column.includes:tickets.whereboard\u id:1,然后是@columns或@columns.tickets.wheresprint\u id:10似乎会在rails控制台中为我导致N+1。它必须使用内存中的Ruby代码执行where子句,而不是运行SQL查询,但我看到它输出SELECT。。。从每次迭代sprint_id=10的记录单开始。小心那些to_a调用,在不知道记录数量的情况下加载内存中的所有内容是一种糟糕的做法。使用Column.whereboard_id:1.pulk:id以更高效的方式获取id,以后可能需要再进行一次sql查询来迭代记录,但这会产生很大影响