Построить JSON объект иерархии из запроса postgres. Это правильно? - PullRequest
1 голос
/ 19 марта 2020

Я не мог понять, как я могу получить иерархический объект из запроса json.

Мой пример данных:

CREATE TABLE
    "postgres"."public"."owner"
    (
        owner_id INTEGER,
        name text,
        mail text
    )
;

insert into owner (owner_id, name, mail) values
  (1, 'Owner1', 'mail@owner1.do.main'),
  (2, 'Owner2', 'mail@owner2.do.main')
;

CREATE TABLE
    "postgres"."public".ip
    (
        owner_id INTEGER,
        status text,
        ip inet,
        host text
    )
;
insert into ip (owner_id, status, ip, host) values
  (1, 'active', '12.34.56.78', 'host78.owner1.do.main'),
  (1, 'active', '12.34.56.79', 'host79.owner1.do.main'),
  (1, 'active', '12.34.56.80', 'host80.owner1.do.main'),
  (1, 'tests failed', '12.34.56.81', 'host81.owner1.do.main'),
  (1, 'tests failed', '12.34.56.82', 'host82.owner1.do.main'),
  (2, 'active', '34.56.78.1', 'host1.owner2.do.main'),
  (2, 'active', '34.56.78.2', 'host2.owner2.do.main'),
  (2, 'not listed', '34.56.78.3', 'host3.owner2.do.main'),
  (2, 'not listed', '34.56.78.4', 'host4.owner2.do.main')
;

Моя предполагаемая структура:

{
  "Owner1": {
    "mail": "mail@owner1.do.main",
    "ips": {
      "active": {
        "12.34.56.78": "host78.owner1.do.main",
        "12.34.56.79": "host79.owner1.do.main",
        "12.34.56.80": "host80.owner1.do.main"
      },
      "tests failed": {
        "12.34.56.81": "host81.owner1.do.main",
        "12.34.56.82": "host82.owner1.do.main"
      }
    }
  },
  "Owner2": {
    "mail": "mail@owner2.do.main",
    "ips": {
        "active": {
          "34.56.78.1": "host1.owner2.do.main",
          "34.56.78.2": "host2.owner2.do.main"
        },
        "not listed": {
          "34.56.78.3": "host3.owner2.do.main",
          "34.56.78.4": "host4.owner2.do.main"
        }
    }
  }
}

После долгих попыток я пришел к следующему запросу:

select json_object_agg(name, status_ips)
from (
        select name, json_build_object('mail', mail, 'ips', json_object_agg(status, ips)) as status_ips
        from (
                select owner_id, status, json_object_agg(ip, host) as ips
                from ip
                group by owner_id, status
        ) IPS
        join owner
        using (owner_id)
        group by name, mail
) OWNER_IPS;

Поскольку у меня есть 2 подзапроса, мой вопрос: это слишком сложно? Есть ли лучшие способы получить мой результат?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...