Выберите конкретную запись в JSON с PostgreSQL - PullRequest
1 голос
/ 08 марта 2019

У меня есть следующий JSON, который хранится в поле jsonb с именем «Данные» в базе данных PostgreSQL:

{
    "CompetitionData" :
    {
        "StartDate" : "12.06.2018",
        "Name" : "TestCompetition",
        "Competitors" :
        [
            {
                "Id" : "100",
                "Name" : "John",
                "Age" : "24",
                "Score" : "98",
                "Shoes":
                {
                    "Brand" : "Nike"
                }
            },
            {
                "Id" : "200",
                "Name" : "Adam",
                "Age" : "32",
                "Score" : "78",
                "Shoes":
                {
                    "Brand" : "Adidas"
                }
            }
        ]
    }
}

Я пытаюсь получить конкретную запись в конкурентах, например, например.

SELECT * FROM Competitors WHERE Shoes = "Nike";

И результат должен выглядеть так:

{
       "Id" : "100",
       "Name" : "John",
       "Age" : "24",
       "Score" : "98",
       "Shoes":
       {
           "Brand" : "Nike"
       }
}

Я попробовал следующий запрос, но я продолжаю возвращать всех конкурентов:

SELECT jsonb_array_elements(public."Competitions"."Data"->'CompetitionData'->'Competitors') as test
FROM public."Competitions" WHERE public."Competitions"."Data" @> '{"CompetitionData":{"Competitors":[{"Shoes":{"Brand":"Nike"}}]}}';

Можно ли вернуть только конкурента с обувной маркой "Nike"?

Ответы [ 2 ]

2 голосов
/ 08 марта 2019

Используйте jsonb_array_elements в предложении from

SELECT j.* FROM
t cross join lateral 
  jsonb_array_elements(data->'CompetitionData'->'Competitors') as j(comp)
where j.comp->'Shoes'->>'Brand' = 'Nike'

Демо

0 голосов
/ 08 марта 2019

Почему вы хотите сохранить его в jsonb?Просто нормализуйте его в базе данных:

CREATE TABLE competitor_shoe (
  name  text PRIMARY KEY,
  brand text NOT NULL
);

CREATE TABLE competitor (
  id    int  PRIMARY KEY,
  name  text NOT NULL,
  age   int  NOT NULL,
  score int  NOT NULL,
  shoe  text NOT NULL REFERENCES competitor_shoe(name)
);

CREATE TABLE competition (
  name       text PRIMARY KEY, 
  start_date date NOT NULL
);

CREATE TABLE competition_competitor (
  competition text REFERENCES competition,
  competitor  int  REFERENCES competitor,
  PRIMARY KEY (competition,competitor)
);


INSERT INTO competitor_shoe
VALUES ('shoes1', 'Nike'), 
  ('shoes2', 'Adidas');

INSERT INTO competitor 
VALUES (100,'John',24,98,'shoes1'),
  (200,'Adam',32,78,'shoes2');

INSERT INTO competition 
VALUES (
  'TestCompetition',
  '12.06.2018'
);

INSERT INTO competition_competitor
VALUES ('TestCompetition', 100), ('TestCompetition', 200);


-- query the data
SELECT * 
FROM   competitor c
JOIN   competitor_shoe cs
ON     c.shoe = cs.name
WHERE  brand = 'Nike';

-- query the data and return it as json object
SELECT to_jsonb(c) || jsonb_build_object('shoe', to_jsonb(cs)) as data
FROM   competitor c
JOIN   competitor_shoe cs
ON     c.shoe = cs.name
WHERE  brand = 'Nike';
...