2015-01-29 2 views
5

가끔 내포 된 키가있는 JSONB 필드가 있습니다. 예 : 나는 .filter(TestMetadata.metadata_item.has_key(nested_field))
을 할 경우JSAlB의 중첩 키에 따른 SQLAlchemy 필터

{"nested_field": {"another URL": "foo", "a simple text": "text"}, "first_metadata": "plain string", "another_metadata": "foobar"}

나는이 기록을 얻을.

중첩 키가 있는지 어떻게 검색합니까? ("a simple text")를 ? operator와 중첩 된 필드의 존재에 대한

답변

10

귀하의 테스트 문자열에 대한 다음과 같은 작업을해야합니다 :

SQLAlchemy documentation of JSONB에 따라
class TestMetadata(Base): 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    metadata_item = Column(JSONB) 

(경로 인덱스 작업 예를 들어 검색하는) :

expr = TestMetadata.metadata_item[("nested_field", "a simple text")] 
q = (session.query(TestMetadata.id, expr.label("deep_value")) 
    .filter(expr != None) 
    .all()) 

아래 SQL 생성해야한다 :

SELECT testmetadata.id AS testmetadata_id, 
     testmetadata.metadata_item #> %(metadata_item_1)s AS deep_value 
FROM testmetadata 
WHERE (testmetadata.metadata_item #> %(metadata_item_1)s) IS NOT NULL 
-- @params: {'metadata_item_1': u'{nested_field, a simple text}'} 
+4

굉장 전자 ... IMHO Path 인덱스가 중첩 된 JSON 인 것은 분명하지 않지만 어쩌면 그것은 나 일 수 있습니다. 그건 그렇고, 값에 대한 검사를 위해서 내부적으로 사용하고 싶습니다. : '.filter (TestMetadata.metadata_item [key] .astext == value)' 여기서 key는 튜플입니다 – Boaz

+1

물론, 질문은 * 존재 여부를 확인하고 * 값의 유형을 확인하지 않는 것 *이 더 많습니다. – van

+1

당신은 완전히 맞아 ... 나는 둘 다 필요했다. (그리고 has_key가 튜플을 지원하지 않기 때문에 분명히 impl.이 다르다) – Boaz

1

이 쿼리 테스트의 -> operator와 중첩 된 JSON 객체를 추출 후 : 일반 GIN 인덱스가이 쿼리를 지원하지 않습니다

SELECT EXISTS (
    SELECT 1 
    FROM testmetadata 
    WHERE metadata_item->'nested_field' ? 'a simple text' 
    ); 

참고. 이 과정을 빠르게 진행하려면 metadata_item->'nested_field'expression index이 필요합니다.

CREATE INDEX testmetadata_special_idx ON testmetadata 
USING gin ((metadata_item->'nested_field')); 

비슷한 경우에 example in the manual가 있습니다. SQLAlchemy의와