JSON 유형 내부의 배열 요소 쿼리


118

jsonPostgreSQL 9.3 에서 유형 을 테스트하려고합니다 . 라는 테이블에라는 열
이 있습니다 . JSON은 다음과 같습니다.jsondatareports

{
  "objects": [
    {"src":"foo.png"},
    {"src":"bar.png"}
  ],
  "background":"background.png"
}

'objects'배열의 'src'값과 일치하는 모든 보고서에 대한 테이블을 쿼리하고 싶습니다. 예를 들어, 일치하는 모든 보고서에 대해 DB를 쿼리 할 수 'src' = 'foo.png'있습니까? 다음과 일치 할 수있는 쿼리를 성공적으로 작성했습니다 "background".

SELECT data AS data FROM reports where data->>'background' = 'background.png'

그러나 "objects"값의 배열이 있기 때문에 작동하는 것을 작성할 수 없습니다. 일치하는 모든 보고서에 대해 DB를 쿼리 할 수 'src' = 'foo.png'있습니까? 이 소스를 살펴 봤지만 여전히 얻을 수 없습니다.

나는 또한 이와 같은 것을 시도했지만 아무 소용이 없습니다.

SELECT json_array_elements(data->'objects') AS data from reports
WHERE  data->>'src' = 'foo.png';

저는 SQL 전문가가 아니기 때문에 제가 뭘 잘못하고 있는지 모르겠습니다.

답변:


214

json Postgres 9.3 이상

절의 json_array_elements()측면 조인에서 함수 가있는 JSON 배열의 중첩을 해제하고 FROM해당 요소를 테스트합니다.

WITH reports(data) AS (
   VALUES ('{"objects":[{"src":"foo.png"}, {"src":"bar.png"}]
           , "background":"background.png"}'::json)
   ) 
SELECT *
FROM   reports r, json_array_elements(r.data#>'{objects}') obj
WHERE  obj->>'src' = 'foo.png';

CTE ( WITH쿼리) 단지 테이블을 대체 reports.
또는 단일 수준의 중첩에 해당합니다.

SELECT *
FROM   reports r, json_array_elements(r.data->'objects') obj
WHERE  obj->>'src' = 'foo.png';

->>, ->#>연산자는 매뉴얼에 설명되어 있습니다.

두 쿼리 모두 암시 적 JOIN LATERAL.

SQL 바이올린.

밀접하게 관련된 답변 :

jsonb Postgres 9.4 이상

동등한 jsonb_array_elements().

더 좋은 방법은 새로운 "contains"연산자를 사용하는 것입니다 @>(표현식에서 일치하는 GIN 인덱스와 함께 사용하는 것이 가장 좋습니다 data->'objects').

CREATE INDEX reports_data_gin_idx ON reports
USING gin ((data->'objects') jsonb_path_ops);

SELECT * FROM reports WHERE data->'objects' @> '[{"src":"foo.png"}]';

objects에 JSON 배열이 포함 되어 있으므로 검색어의 구조를 일치시키고 배열 요소도 대괄호로 묶어야합니다. 일반 레코드를 검색 할 때 배열 대괄호를 삭제하십시오.

자세한 설명 및 추가 옵션 :


1
@pacothelovetaco : jsonb9.4 페이지 에 대한 업데이트를 추가했습니다 . 참고 : 간단한 경우 (1 단계 중첩)의 경우 ->연산자는 json9.3 페이지에 대한 트릭도 수행합니다 .
Erwin Brandstetter 2015 년

1
@pacothelovetaco, 9.3 페이지의 경우 '#>'은 비밀 소스가 아니며 '->'는 json objec도 반환하므로 귀하의 경우에 적합합니다. '#>'은 '{}'에 경로를 쉽게 지정할 수 있으므로 중첩 된 json 경로 케이스에서 더 유용합니다.
Gob00st

1
@> '[{ "src": "foo.png"}]'; 어디 조건에서 잘 작동하지만 이와 같은 특정 개체를 삭제하는 방법은 무엇입니까? 나는이 객체의 색인을 모른다. 키 값으로 삭제하고 싶습니다.
Pranay Soni

1
@PranaySoni : 같은 새 질문 문의하시기 바랍니다 질문을 . 댓글은 장소가 아닙니다. 컨텍스트를 위해 언제든지이 링크에 연결할 수 있습니다.
Erwin Brandstetter

@ErwinBrandstetter 님, 부분 일치로 두 문서를 모두 찾을 수 있습니까? 예를 들어 '[{ "src": ". png"}]'와 같은 두 레코드를 모두 얻고 싶습니다.
Pyrejkee

8

열을 json 유형으로 사용하여 테이블 만들기

CREATE TABLE friends ( id serial primary key, data jsonb);

이제 json 데이터를 삽입하겠습니다.

INSERT INTO friends(data) VALUES ('{"name": "Arya", "work": ["Improvements", "Office"], "available": true}');
INSERT INTO friends(data) VALUES ('{"name": "Tim Cook", "work": ["Cook", "ceo", "Play"], "uses": ["baseball", "laptop"], "available": false}');

이제 데이터를 가져 오는 몇 가지 쿼리를 만들어 보겠습니다.

select data->'name' from friends;
select data->'name' as name, data->'work' as work from friends;

결과가 반전 된 쉼표 ( ") 및 대괄호 ([])와 함께 제공된다는 것을 눈치 채 셨을 것입니다.

    name    |            work            
------------+----------------------------
 "Arya"     | ["Improvements", "Office"]
 "Tim Cook" | ["Cook", "ceo", "Play"]
(2 rows)

이제 값만 검색하려면 ->>

select data->>'name' as name, data->'work'->>0 as work from friends;
select data->>'name' as name, data->'work'->>0 as work from friends where data->>'name'='Arya';

22
이것은 질문에 대한 식별 가능한 연결없이 유쾌하게 형식화 된 소음입니다.
Erwin Brandstetter 2019

4
나는 이것이 유용하다는 것을 알았다. 쇼는 어떻게 jsonb의 배열로 드릴 수
GavinBelson

0

data-> 'objects'-> 0-> 'src'를 데이터-> 'objects'-> 0-> 'src'= 'foo.png'테이블에서 SRC로 선택하십시오.


2
이것은 인덱스가 0 인 경우에만 유용합니다.
Buyut Joko Rivai

예,하지만 행 현명하게 매핑 할 배열 객체를 분해하는 방법이 있으며이를 사용할 수 있습니다. 내가 틀렸다면 정정하십시오.
anand shukla

확신 할 수없는 좋은 해결책이 아닙니다. "src"는 위치 0에 있습니다.
simUser
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.