2015-01-29 14 views
5

Mam pole JSONB, które czasami ma zagnieżdżone klucze. Przykład:Filtr SQLAlchemy według kluczy zagnieżdżonych w JSONB

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

Jeśli robię .filter(TestMetadata.metadata_item.has_key(nested_field))
uzyskać ten rekord.

Jak mogę wyszukać istnienie zagnieżdżonego klucza? ("a simple text")

Odpowiedz

10

Z SQLAlchemy następujące powinny pracować dla Twojego ciąg testu:

class TestMetadata(Base): 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    metadata_item = Column(JSONB) 

zgodnie SQLAlchemy documentation of JSONB (szukaj operacji indeksu Ścieżka przykład):

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

który powinien generować poniżej 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

Awesom e ... IMHO nie jest jasne, że Indeks ścieżki jest zagnieżdżonym JSON, ale może to tylko ja. Przy okazji - dla sprawdzenia pod kątem wartości wolałbym użyć wewnętrznego: '.filter (TestMetadata.metadata_item [klucz] .astext == wartość)' Gdzie klucz jest krotką – Boaz

+1

Jasne, chociaż twoje pytanie było więcej * sprawdź istnienie * i nie * sprawdź wartość * typu rzeczy. – van

+1

masz całkowitą rację ... Potrzebowałem ich obu (i najwyraźniej imp. Jest inne, ponieważ has_key nie obsługuje krotki) – Boaz

1

Zapytanie testy dla istnienia pola zagnieżdżonej z ? operator po ekstrakcji zagnieżdżony obiekt JSON z -> operator:

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

Należy zauważyć, że zwykły wskaźnik GIN nie obsługuje tego zapytania. Aby to zrobić szybko, potrzebujesz expression index na metadata_item->'nested_field'.

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

Dla podobnego przypadku istnieje example in the manual.

Powiązane problemy