【问题标题】:Get an array of hashes corresponding to the selected values with ActiveRecord使用 ActiveRecord 获取与所选值对应的哈希数组
【发布时间】:2017-01-09 10:29:59
【问题描述】:

我有一个使用 ActiveRecord 查询的 sql 数据库。 (ActiveRecord 版本为 4.2.5.1)

我的查询如下所示:

User.
  select('COUNT (DISTINCT user_id) as user_count').
  select("date_trunc('month', created_at) as month").
  select('city').
  where('created_at > ?', 1.year.ago.utc.to_s(:db)).
  group('month, city').
  to_a.map do |row|
  {
    user_count: row.user_count,
    month: row.month,
    city: row.city
  }

我得到这样的结果:

[
    [  0] {
        :user_count => 165,
             :month => 2015-09-01 00:00:00 UTC,
              :city => "Paris"
    },
    [  1] {
        :user_count => 33,
             :month => 2015-09-01 00:00:00 UTC,
              :city => "Berlin"
    },
    ...
]

这很好。

但是,使用此查询:

User.
  select('COUNT (DISTINCT user_id) as user_count').
  select("date_trunc('month', created_at) as month").
  select('city').
  where('created_at > ?', 1.year.ago.utc.to_s(:db)).
  group('month, city').
  to_a

我得到这样的结果:

[
    [  0] #<User:0x007facebac3560> {
           :user_id => nil,    # wtf is this
              :city => "Paris"
                               # where is the month?
    },
    [  1] #<User:0x007facebac33a8> {
           :user_id => nil,
              :city => "Berlin"
    },
    ...
]

这不好。

为什么即使我选择了我想要的行,我也必须手动映射结果?

理想情况下,我想要的是这样的:

User.
  select(...).
  where(...).
  group(...).
  to_array_of_hashes_with_the_keys_i_selected

请注意,如果我的查询是自定义查询,to_a 会执行我想要的操作,例如:

ActiveRecord::Base.connection.execute(<<~SQL
  SELECT COUNT (DISTINCT user_id) as user_count, date_trunc('month', created_at) as month,  city
  FROM users
  WHERE created_at > '2015-09-01 13:28:40'
  GROUP BY month, city
SQL
).to_a # this is fine

【问题讨论】:

    标签: sql ruby activerecord


    【解决方案1】:

    来自How to convert activerecord results into a array of hashes,我可以做到:

    User.
      select(...).
      where(...).
      group(...).
      as_json
    

    我得到了

    [
        [  0] {
               "user_id" => nil,
                  "city" => "Paris",
            "user_count" => 165,
                 "month" => 2015-09-01 00:00:00 UTC
        },
        ...
    

    不完全是我选择的,但足够接近。

    .as_json.map{|e|e.except('user_id')} 给了我想要的东西

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-11
      • 2018-02-04
      • 2011-11-10
      • 1970-01-01
      相关资源
      最近更新 更多