#title JSON 
[[TableOfContents]]

==== JSON 데이터 타입 ====
{{{
CREATE TABLE posts
(
  id serial NOT NULL,
  meta JSON
);
}}}

입력은 valid한? well-formed? json 타입이어야 입력된다.
{{{
INSERT INTO posts (id, meta)
VALUES (
  1, 
  '{ 
    "author": "outsider", 
    "authorId": 43434,
    "sns": { 
      "facebook": "https://facebook.com",
      "twitter": "https://twitter.com"
    },
    "createAt": "2014-06-14", 
    "category": ["pg", "tech", "dev"]
  }'
);
}}}

==== json vs jsonb ====
 * json 자료형은 9.2 버전, 입력된 그 자료 그대로 저장
 * jsonb 자료형은 9.4 버전, 의미단위(key-value 기준)로 선처리를 해서 저장하므로 입력부하 있음. 
  * 공백문자를 무시하며, 
  * value 값은 적당한 형변환을 하며, 
  * 그 key 이름이 중복될 경우는 마지막 것을 사용하며, 
  * '''key는 정렬'''되며,
  * @> 등과 같은 jsonb 데이터 타입에만 사용할 수 있는 부가 연산자들이 있음.


==== 조회 ====
{{{
SELECT meta->'author' FROM posts; 
-- "outsider"
 
SELECT meta->'sns'->'facebook' FROM posts;
-- "https://facebook.com"
 
SELECT meta->'sns'->>'facebook' FROM posts;
-- https://facebook.com
 
SELECT meta#>'{category, 2}' FROM posts;
-- "dev"
}}}

 * -> 는 json 배열이나 객체를 반환
 * ->> 는 문자열 반환(meta->'sns'->>'facebook'는 가능, meta->>'sns'->'facebook'는 불가능)
 * #> 는 배열값 반환(meta#>'{category, 2}'는 category 키의 3번째값)
 * 이런 연산자들은 where column1 ->>'hostname' = 'myhost' 과 같이 여러 절에 그대로 사용 가능

==== JSON 키에 대한 인덱스 ====
괄호가 2개 들어간 것을 주의 깊게 봐라. 문법이다.
{{{
CREATE INDEX posts_idx1 ON posts((meta->>'authorId'));
CREATE INDEX posts_idx2 ON posts((meta->'sns'->>'facebook'));
}}}

==== 참고자료 ====
 * http://blog.outsider.ne.kr/1061
 * http://postgresql.kr/blog/postgresql_jsonb.html
 * http://www.postgresql.org/docs/9.4/static/functions-json.html