PostgreSQL의 jsonb 배열에서 특정 객체를 얻는 방법은 무엇입니까?


16

나는 대략 다음과 같은 json 배열을 보유하는 'user'라는 필드를 가지고 있습니다 :

"user":

[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]

이제 다음과 같은 쿼리를 원합니다.

select count from tablename where id = "1"

countPostgreSQL 9.4의 json 객체 배열에서 특정 필드를 가져올 수 없습니다 .

답변:


17

정규화 된 스키마에 값을 저장하는 것이 훨씬 더 효율적입니다. 즉, 현재 설정에서 작동하도록 할 수도 있습니다.

가정

이 테이블 정의를 가정하면 :

CREATE TABLE tbl (tbl_id int, usr jsonb);

"user"는 예약어 이며 열 이름으로 큰 따옴표를 사용해야합니다. 그렇게하지 마십시오. usr대신에 사용 합니다.

질문

쿼리는 (현재 삭제 된) 의견처럼 보이지 않습니다.

SELECT t.tbl_id, obj.val->>'count' AS count
FROM   tbl t
JOIN   LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE  t.usr @> '[{"_id":"1"}]';

있다 3 가지 기본 단계 :

1. 적격 한 행을 저렴하게 식별

WHERE t.usr @> '[{"_id":"1"}]'JSON 배열에서 일치하는 객체로 행을 식별합니다. 표현식은에 일반적인 GIN 인덱스를 사용하여 jsonb열 또는 더 전문 연산자 클래스 하나 jsonb_path_ops:

CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);

추가 된 WHERE절은 논리적으로 중복 되지만 색인을 사용해야합니다. join 절의 표현식은 지금까지 자격을 갖춘 모든 행에서 배열을 중첩 해제 한 후에 만 동일한 조건을 적용합니다 . 인덱스 지원을 통해 Postgres는 한정 객체가 포함 된 행만 처리합니다. 작은 테이블의 경우 문제가되지 않으며 큰 테이블과 큰 차이 가있는 한정된 행과 큰 차이가 있습니다.

관련 :

2. 배열에서 일치하는 객체 식별

와 Unnest jsonb_array_elements(). ( unnest()Postgres 배열 유형에만 유용합니다.) 실제로 일치하는 객체에만 관심이 있으므로 결합 조건을 즉시 필터링하십시오.

관련 :

3. 중첩 키 값 추출 'count'

적격 객체가 추출 된 후 간단히 다음을 수행하십시오 obj.val->>'count'.


2
어디에서 obj(value)왔습니까? 그것은에 LATERAL JOIN는, jsonb_array_elements또는 다른 곳?
Tyler DeWitt

서식이 망가진 것 같습니다. 오전 나는 것을 제대로 읽기 JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)와 그 obj(value)테이블 및 열 별칭입니다? 이 예에서 obj테이블 별칭 인 경우 별칭은 무엇입니까? 세트가 jsonb_array_elements? 에서 반환되었습니다 .
Tyler DeWitt

1
예, 그렇습니다 스크램블 된 댓글을 삭제했습니다.
Erwin Brandstetter

열 별칭을 사용해야합니까? 내 테스트 JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'에서 같은 효과가있었습니다 (한 번 select 문을 업데이트하여 value대신 사용하십시오 val). jsonb_array_elements(t.usr)열이 하나만있는 테이블 을 반환하는 것으로 나타납니다 . postgres는 똑똑하고 실현되는 obj ->>것과 동일 obj.val ->>합니까?
Tyler DeWitt

단 하나의 열만으로 Postgres는 주어진 별칭을 테이블 열 이름으로 사용합니다. 둘 이상의 열을 반환하는 많은 집합 반환 함수가 있으므로 명시 적입니다.
Erwin Brandstetter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.