Rails PostgreSQL jsonb GROUP BY 查询内部动态键
Rails PostgreSQL jsonb GROUP BY query on internal dynamic keys
我有一个 ActiveRecord 模型,我们称它为 API::Response
,其中我们有一个名为 error_messages
的列,它存储 API 调用失败时的错误消息。
API::Response
的结构类似于:
#<API::Response:0x0000000019579298
id: "fffefdae43c0",
api_id: "11c91374f10e",
parent_id: nil,
code: "ABC123",
meta_field: "{}",
lock_version: 1,
created_at: Thu, 01 Feb 2019 15:28:37 UTC +00:00,
updated_at: Tue, 09 Oct 2019 20:32:03 UTC +00:00,
version: 1538352000,
error_messages: {"api_failure_1"=> "API failure reason 1", "api_failure_2"=> "API failure reason 2"},
output_data: { "foo" => "bar"},
override_applied: false>
我想要做的是得到一个结果,我在 error_messages
列中按 keys
分组,并得到每个键的出现次数:
所以有些像:
key | count
-----------------------------
api_failure_1 | 1
api_failure_2 | 3
some_other_failure | n
...
其中 error_messages
jsonb 字段中的 keys
是动态的。
我尝试做类似
的事情
API::Response.where.not("error_messages = '{}'").group("error_messages").count
但这只是让我计算每个不同的 error_messages
=> {
{"api_failure_1"=> "API failure 1",
"api_failure_2"=> "API failure 2"}=>1,
{"api_failure_1"=> "API failure 1",
"api_failure_3"=> "API failure 3"}=>1
}
而不是每个键的计数。
我在 Rails 5.2 和 PostgreSQL 10.4
非常感谢任何指点或帮助。
我认为 PostgreSQL 无法对 jsonb 字段中的键进行分组。我认为您需要做的方法:查询所有有错误的响应,然后对所有找到的记录使用循环以使用正常 Ruby 代码进行分组。
# not tested, but something like:
errors = API::Response.where.not("error_messages = '{}'").pluck(:error_messages)
error_holder = []
errors.each do |error|
error_holder << error.keys
end
counts = Hash.new(0)
error_holder.flatten.each { |name| counts[name] += 1 }
puts counts
事实上...您可以让它发挥作用!执行以下查询:
query = <<-SQL
select errors.types, COUNT(errors.types)
from (select jsonb_object_keys(error_messages) as types from api_responses) errors
group by errors.types
SQL
your_result = API::Response.find_by_sql(query)
我仍然建议创建一个视图,这样访问它会容易得多。
我有一个 ActiveRecord 模型,我们称它为 API::Response
,其中我们有一个名为 error_messages
的列,它存储 API 调用失败时的错误消息。
API::Response
的结构类似于:
#<API::Response:0x0000000019579298
id: "fffefdae43c0",
api_id: "11c91374f10e",
parent_id: nil,
code: "ABC123",
meta_field: "{}",
lock_version: 1,
created_at: Thu, 01 Feb 2019 15:28:37 UTC +00:00,
updated_at: Tue, 09 Oct 2019 20:32:03 UTC +00:00,
version: 1538352000,
error_messages: {"api_failure_1"=> "API failure reason 1", "api_failure_2"=> "API failure reason 2"},
output_data: { "foo" => "bar"},
override_applied: false>
我想要做的是得到一个结果,我在 error_messages
列中按 keys
分组,并得到每个键的出现次数:
所以有些像:
key | count
-----------------------------
api_failure_1 | 1
api_failure_2 | 3
some_other_failure | n
...
其中 error_messages
jsonb 字段中的 keys
是动态的。
我尝试做类似
的事情API::Response.where.not("error_messages = '{}'").group("error_messages").count
但这只是让我计算每个不同的 error_messages
=> {
{"api_failure_1"=> "API failure 1",
"api_failure_2"=> "API failure 2"}=>1,
{"api_failure_1"=> "API failure 1",
"api_failure_3"=> "API failure 3"}=>1
}
而不是每个键的计数。
我在 Rails 5.2 和 PostgreSQL 10.4
非常感谢任何指点或帮助。
我认为 PostgreSQL 无法对 jsonb 字段中的键进行分组。我认为您需要做的方法:查询所有有错误的响应,然后对所有找到的记录使用循环以使用正常 Ruby 代码进行分组。
# not tested, but something like:
errors = API::Response.where.not("error_messages = '{}'").pluck(:error_messages)
error_holder = []
errors.each do |error|
error_holder << error.keys
end
counts = Hash.new(0)
error_holder.flatten.each { |name| counts[name] += 1 }
puts counts
事实上...您可以让它发挥作用!执行以下查询:
query = <<-SQL
select errors.types, COUNT(errors.types)
from (select jsonb_object_keys(error_messages) as types from api_responses) errors
group by errors.types
SQL
your_result = API::Response.find_by_sql(query)
我仍然建议创建一个视图,这样访问它会容易得多。