当查询包含关系时,如何在包含的表上使用模式匹配?

时间:2014-10-21 00:02:15

标签: ruby-on-rails postgresql rails-activerecord arel

订单有很多LineItems。 LineItems有名字,比如“car”。我想查找所有包含名称与某个模式匹配的订单项的订单。

我知道我可以做LineItem.where('name ~* :pat', pat: 'car'),例如。

我也知道我能做到

Order.where.not(state: "cancelled")
     .includes(:line_items)
     .where(line_items: { name: "car" })

我不确定组合这两个查询的语法。我想它就像是,

Orders.where.not(state: 'cancelled')
      .includes(:line_items)
      .where(line_items: ['name ~* :pat', pat: 'car'])

这对google来说很棘手,所以我想我会把它给你。

注意:上次我有关于Rails activerecord的问题时,解决方案的一部分是检查SQL。但是,在这种情况下,使用includes方法会导致一些疯狂的可怕SQL。试试这样的事情,

Order.includes(:line_items).where(line_item: { name: "car"}).to_sql

在你的rails控制台中玩得很开心!

注意:我明确需要帮助解决这个问题的标题。

1 个答案:

答案 0 :(得分:0)

rails guide中所述,

  

使用这样的地方只有在你传递哈希时才会有效。   对于SQL片段,您需要使用引用强制连接表:

Post.includes(:comments).where("comments.visible = true").references(:comments)

所以在我的情况下,查询将是:

Orders.where.not(state: 'cancelled')
      .includes(:line_items)
      .where('line_items.name ~* ?', 'car').references(:line_items)

这将返回包含名称与给定正则表达式匹配的订单项的所有订单,并预先加载这些订单项。如果您不想预加载订单项,请使用joins代替includes

如果您想为每个订单预加载所有订单项,我不知道您会怎么做,无论条件如何(但希望我不需要^ o ^ //)

编辑:this article详细说明了究竟发生了什么,并回答了我的第二个问题。要预加载您必须使用的所有订单项... preload ha!

Orders.where.not(state: 'cancelled')
      .joins(:line_items) # note the joins
      .where('line_items.name ~* ?', 'car').references(:line_items)
      .preload(:line_items)

如果你在这里再次使用.includes,你将会失望。它必须是preload。此查询获取我想要的订单,并预加载所有订单项,无论它们是否与用于过滤订单的正则表达式匹配。