Rails PostgreSQL jsonb GROUP GROUP запрос на внутренние динамические ключи - PullRequest
1 голос
/ 14 мая 2019

У меня есть модель 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>

То, что я хочу сделать, это получить результат, в котором я группирую по keys в столбце error_messages, и получить количество вхождений каждого ключа:

так что-то вроде:

key                   | count
-----------------------------
api_failure_1         |  1
api_failure_2         |  3
some_other_failure    |  n
...

где keys в поле error_messages jsonb являются динамическими.

Я пытался сделать что-то вроде

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

Любые указатели или помощь очень ценится.

Ответы [ 2 ]

3 голосов
/ 14 мая 2019

На самом деле ... вы можете заставить его работать!Выполните следующий запрос:

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)

Я бы все же посоветовал создать представление, которое значительно облегчит доступ к нему.

0 голосов
/ 14 мая 2019

Я не думаю, что 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
...