Я работаю над приложением Rails, которое использует тип данных Postgres JSON
. У меня есть столбец JSON с именем data
в таблице с именем reports
. Скажем, у меня есть несколько записей вроде этого:
Entry 1: {"objects":[{"album": 1, "src":"fooA.png", "pos": "top"}, {"album": 2, "src":"barB.png", "pos": "top"}], "background":"background.png"}
Entry 2: {"objects":[{"album": 1, "src":"fooA.png", "pos": "top"}, {"album": 2, "src":"barC.png", "pos": "top"}], "background":"bacakground.png"}
Entry 3: {"objects":[{"album": 1, "src":"fooA.png", "pos": "middle"},{"album": 2, "src":"barB.png", "pos": "middle"}],"background":"background.png"}
Entry 4: {"objects":[{"album": 1, "src":"fooA.png", "pos": "top"}, {"album": 3, "src":"barB.png", "pos": "top"}], "background":"backgroundA.png"}
Что бы я хотел сделать, это вернуть разные комбинации записей, имеющих один и тот же альбом, src и background (ПРИМЕЧАНИЕ: в objects
node порядок элементов массива не имеет значения). Например, запрос должен соответствовать элементам 1,3 как одна группа, запись 2, как и другая и т.д. Цель состоит в том, чтобы найти верхние 3 наиболее распространенные комбинации. Я знаю, как это сделать с помощью Ruby, но мне нужно будет запросить большую выборку записей, а затем перебрать все из них. Кажется более эффективным использовать Postgres, если он может справиться с этой задачей. Мне не хватает эксперта SQL, чтобы узнать, возможно ли это.
Это результат, который я ищу. Внутри objects
записи 1 и 3 содержат {"album": 1, "src":"fooA.png"}, {"album": 2, "src":"barB.png"}
, а оба имеют совпадение backgrounds
. Я хотел бы сгруппировать их как одну комбинацию со счетом 2.
Так как запись 2 не соответствует ни одному элементу по этому критерию, то это еще одна комбинация со счетом 1. Запись 4 также считается другой комбинацией со счетом 1. Таким образом, результат, который я получил после:
ids | count
--------------
1,3 | 2
2 | 1
4 | 1
или
combinations | count
---------------------------------------------------------------------------------------------------------------------------------------------------
{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"}, {"album": 2, "src":"barB.png", "pos": "top"}], "background":"background.png"} | 2
{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"}, {"album": 2, "src":"barC.png", "pos": "top"}], "background":"bacakground.png"} | 1
{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"}, {"album": 3, "src":"barB.png", "pos": "top"}], "background":"backgroundA.png"} | 1
Что легче сделать.
В моих фактических данных у меня есть значения, отличные от album
и src
в массиве JSON в objects
node. Вы заметите, что я включил pos
, чтобы показать этот случай. Мне нужно только использовать значения album
, src
и background
для соответствия комбо. Я надеялся игнорировать любые другие ценности.
Примечание
Когда я тестировал решение Erwin, я продолжал получать эту ошибку, и я знаю, почему:
ERROR: cannot call json_populate_recordset on a nested object
Мои значения json на самом деле немного сложнее. Например:
{"objects":[{"album": 1, "src":"fooA.png", "pos": "top", filters: []}, {"album": 2, "src":"barB.png", "pos": "top", filters: []}
Очевидно, что filters
является вложенным объектом и не поддерживается json_populate_recordset
. Однако, я думаю, я могу обойти это, если нет простой альтернативы. Опять же, я предполагаю, что это возможно?
UPDATE
Из-за опечатки в приведенных выше образцах (что было моей ошибкой) это решение немного неполно. Когда опечатка исправлена, решение не работает. Найдите ответ на эту ситуацию здесь. Но решение Erwin по-прежнему является ответом на случаи, подобные описанным выше.