【问题标题】:ActiveRecord - "includes" & "where" gettting Nil and Not Nil Statement, with other attributesActiveRecord - "includes" & "where" 获取 Nil 和 Not Nil 语句,以及其他属性
【发布时间】:2015-11-27 01:49:53
【问题描述】:

我想使用 '.includes()' 有效地获得结果。

我需要包含表来检索不为零的记录。我需要在查询中保留 included: true

使用 postgres。

角色有很多任务。

任务属于一个角色。

以下方法有效,但从 Roles 表中获取了错误的记录。

Task.includes(:role).where(included: true, roles: {doer: nil})

下一部分是我想要的想法...... 但显然 where 子句的“角色”值语法错误。

Task.includes(:role).where(
    included: true,
    roles: {
        doer != nil    #=> where 'doer' is not 'nil'
    })

我正在寻找一个有效的查询,这就是我进行包含的原因。 如果没有多个 where 查询,我不知道如何获得它。

如果您理解这个问题,但认为可以问得更清楚一些,请告诉我。除非使用了多个 where 语句,否则我在任何地方都找不到这个答案的任何线索。

【问题讨论】:

    标签: ruby-on-rails activerecord null include where


    【解决方案1】:

    我更喜欢尽可能避免使用字符串,所以我会使用以下内容:

    Task.includes(:role).where(included: true).where.not(roles: { doer: nil })

    如果您专门将tasks 表上的included 列设置为具有NULL FALSE,您还可以将where 调用压缩为一个调用,尽管这仍然只会启动一个查询:

    Task.includes(:role).where.not(included: false, roles: { doer: nil })

    就个人而言,如果这些调用很常见,我希望看到一些范围的清理。比如:

    scope :with_doer, -> { includes(:role).where.not(roles: { doer: nil }) }

    因此生成的代码将更具可读性:

    Task.with_doer.where(included: true)

    您显然也可以将此模式扩展到included: true 位。

    请注意,ActiveRecord 查询是建立起来的,然后用一个“踢球者”踢到数据库中,Rails 大部分时间都是偷偷摸摸地通过#inspect#to_a 做的。因此,您无需担心需要将 wherecalls 压缩为单个调用。

    【讨论】:

    • 效果很好。我也喜欢清理,但我需要这样写,对吧?:scope :with_doer, -> { includes(:role).where.not(roles: { doer: nil }) }
    【解决方案2】:

    类似的东西呢:

    Task.includes(:roles).where.not('roles.doer' => nil)
    

    这是一个 rails 4-and-up 的约定,对于 rails 3 它会是这样的:

    Task.includes(:roles).where("roles.doer IS NOT NULL")
    

    而且您不需要包含的属性,可以出于这些目的将其从模型中删除。

    因为你似乎确实需要included(哎呀)

    Task.includes(:roles).where('tasks.included' => true, 'roles.doer' => !nil)
    

    啊.. 我多么喜欢 postgres.. 当你要求效率时,我认为这失败了,但我返回了正确的结果。如果您对选项进行基准测试,这是正确的(我认为)但速度较慢。

    Task.joins('LEFT OUTER JOIN "roles" ON roles.user_id = user_id').where("tasks.included IS true AND roles.doer IS NOT NULL")
    

    【讨论】:

    • 这行不通,因为它丢失了查询的“included: true”部分。
    • 我需要 'included: true' 属性,因为我只想获取用户设置为包含的任务,即 'included: true'。
    • 没有错误,只是返回了一个空数组。不知道为什么,但这里有一个线索,以下两个语句,给出相同的结果,它们唯一不同的地方是 !=! 部分 ... Role.where.not('doer' => !nil) 结果与相同:Role.where.not('doer' => nil) 这是“角色有很多任务”和“任务属于一个角色”。我认为这与空结果有关。当一个不同的答案让我执行纯 SQL 时,它说缺少“FROM”子句
    【解决方案3】:

    这样写 SQL 语句?

    Task.includes(:role).where("included = 'true' AND roles.doer NOT 'nil'")

    【讨论】:

    • 我试了一下,结果显示在“'nill'”处或附近有一个 Synax 错误;我也用 null 试过了。 -- 我希望我在纯 SQL 方面做得足够好,就这样简单地做到这一点,但我的技能还没有达到。
    • 根据答案将 nil 更改为 null 略有变化,即 Task.includes(:role).where("included = true AND roles.doer is NOT null")
    • 我昨天试过了(就我得到的 SQL 和这个查询而言)......我刚刚运行了你的查询并得到了同样的错误:'错误:缺少表“角色”的 FROM 子句条目'
    • 我认为您正在使用pg 我添加了mysql 的想法。这就是为什么它是错误的。对不起
    • 你可以链接where。尝试这个? Task.where(included:true).includes(:role).where('roles.doer IS NOT NULL')
    猜你喜欢
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 2013-07-04
    相关资源
    最近更新 更多