簡體   English   中英

SqlAlchemy + Postgres - 查詢 @> ANY(ARRAY['["...]']::jsonb[])

[英]SqlAlchemy + Postgres - query with @> ANY(ARRAY['["...]']::jsonb[])

我有一個在 sql alchemy 中表示的 postgres 表

from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class ListingDatabaseDocument(Base):
    __tablename__ = 'listing'
    uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True)
    doc = Column(JSONB, nullable=False)

我的doc jsonb 字段看起來像

{"name": "SOME_NAME", "features": ["BALCONY", "GARAGE", "ELEVATOR"]}

現在我想獲取doc->'features'數組包含"ELEVATOR","GARAGE"的所有行 - 在純 sql 中我喜歡這樣做

SELECT * FROM listing
WHERE doc -> 'features' @> ANY(ARRAY['["ELEVATOR","GARAGE"]']::jsonb[])

如何在 SqlAlchemy 中實現這一點? 我試過類似的東西

from sqlalchemy.dialects.postgresql import JSONB, ARRAY
from sqlalchemy.sql.expression import cast
from sqlalchemy import any_

return session.query(ListingDatabaseDocument).filter(
    ListingDatabaseDocument.doc['features'].op('@>')(any_(cast(['ELEVATOR','GARAGE'], ARRAY(JSONB))))
).all()

但它不工作。 感謝幫助 !

如果在 SQLAlchemy 中啟用日志記錄,您可以看到查詢的 SQLAlchemy 版本與 SQL 版本的轉換不同。 具體來說,它兩次轉換為JSONB[] ,而在 SQL 版本中,轉換為JSONB (隱式 - 字符串已經是 JSON)和JSONB

SELECT listing.uuid AS listing_uuid, listing.doc AS listing_doc 
  FROM listing 
  WHERE (listing.doc -> %(doc_1)s) @> ANY (CAST(%(param_1)s::JSONB[] AS JSONB[]))

而不是試圖解決這個問題,我認為 SQL 版本可以簡化為

SELECT uuid, doc 
  FROM listing 
  WHERE doc -> 'features' @> '["ELEVATOR", "GARAGE"]';

和 SQLAlchemy 等價的是

s.query(ListingDatabaseDocument)
.filter(
    ListingDatabaseDocument.doc['features'].op('@>')(
        sa.cast(['ELEVATOR', 'GARAGE'], JSONB)
    )
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM