【问题标题】:Convert postgres hstore sql to Arel将 postgres hstore sql 转换为 Arel
【发布时间】:2012-10-11 12:44:05
【问题描述】:

我在users 表中有一个hstore 列,名为properties

如何将 where 条件中的静态 sql 字符串转换为 aRel 语法?

User.where("properties -> 'is_robber' = 'true'") #=> ...some users

我试过了:

ut = User.arel_table
condition = ut["properties -> 'is_robber'"].eq('true')
User.where(condition) #=> throws pg error

这会产生错误的 sql:

 SELECT "users".* FROM "users" WHERE "users"."properties -> 'is_robber'" = 'true'

与我需要的相比:

SELECT "users".* FROM "users" WHERE "users".properties -> 'is_robber' = 'true'

【问题讨论】:

    标签: ruby-on-rails arel hstore


    【解决方案1】:

    您可以通过创建自己的 Arel::Nodes::InfixOperation 来使用 Arel 完成此操作:

    ut = Arel::Table.new(:user)
    hstore_key = Arel::Nodes::InfixOperation.new("->", ut[:properties], 'is_robber')
    User.where(hstore_key.eq('true'))
    

    将产生:

    SELECT "users".* FROM "users" WHERE "users"."properties" -> 'is_robber' = 'true'
    

    如果你从未听说过中缀表示法,Wikipedia gives a good explaination

    中缀表示法是常见的算术和逻辑公式表示法,其中运算符在它们作用的操作数之间以中缀样式编写(例如 2 + 2)。计算机解析它不像前缀表示法(例如 + 2 2 )或后缀表示法(例如 2 2 + )那么简单,但是由于它的熟悉性,许多编程语言都使用它。

    不幸的是,没有太多关于 Arel 的文档,也没有关于 InfixOperation 节点的文档,所以一开始可能会令人沮丧。当您在寻找如何使用 Arel 执行特定 SQL 操作时,最好的办法是查看 the nodes directory in the source code

    【讨论】:

    • 这不再适用于 arel 6.0.3,现在正确的方法是:hstore_key = Arel::Nodes::InfixOperation.new("->", ut[:properties], Arel: :Nodes::SqlLiteral.new("'is_robber'"))
    【解决方案2】:

    如果您使用 activerecord-postgres-hstore gem,您将能够:

    class User < ActiveRecord::Base
      serialize :data, ActiveRecord::Coders::Hstore
    end
    
    User.where("data -> 'speed' = 'ludicrous'")
    

    更多信息:
    * https://github.com/softa/activerecord-postgres-hstore
    * http://railscasts.com/episodes/345-hstore

    RailsCast Pro 剧集提供了关于自动创建范围、getter 和 setter 的优秀示例代码。

    【讨论】:

    • 感谢您的宝贵时间。我读过/看过这些。我正在使用那个宝石。但我的问题仍然存在:如何将 User.where("data -&gt; 'speed' = 'ludicrous'") 之类的内容转换为 aRel 语法?
    • @shuriu 这是你可以使用的语法;它可以与其他 arel 查询和范围相结合。
    • 这个"data -&gt; 'speed' = 'ludicrous'" 困扰我的原因是它只是一个静态字符串。我想做的是动态构造where:查询另一个数据属性,或更改运算符或值。使用 aRel 很容易,因为您只需链接方法,它就可以正确而神奇地构造您的 sql。无论如何,我想我稍后会编辑这个问题,以便更清楚地了解我想要实现的目标。
    • 好的,因为你可以做所有这些事情 User.active.paid.where(email: @email).where("data -> 'foo' = :value", value: true)
    • 问题是关于Arel。你的答案没有错,只是跑题了。 (这对于 33.4k 的用户来说是令人惊讶的:D)
    猜你喜欢
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    相关资源
    最近更新 更多