簡體   English   中英

SqlAlchemy 從jsonb對象的值中搜索,postgresql

[英]SqlAlchemy search from values of jsonb objects, postgresql

我在表格中有一個 jsonb 字段,其值的形式為

from sqlalchemy.dialects.postgresql import JSONB

class Product(db.Model):
    __tablename__ = 'tbl_product'
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(JSONB, nullable=False, index=True, unique=True)
    slug = db.Column(JSONB, nullable=False, index=True, unique=True)

我有不同語言的產品名稱:

name = {'en': 'Notebook', 'de': 'Notizbuch', ..... }

我想從列名進行搜索,但我不知道它以哪種語言出現,在這里我可以搜索特定的語言:

def get_product_by_name(name, lang):
    q = Product.query
    q = q.filter(Product.slug[lang].as_string() == slug)

    return q.first()

1Q:沒有語言信息怎么搜索? 2Q:我可以訂購帶有語言的產品嗎? 像這樣的東西:

def get_products(lang):
    q = Product.query
    q = q.order_by(Product.name[lang].asc())

    return q.all()

 

在@GordThompson 發表評論后,我改進了查詢以使用jsonb_each_text ,它變得更加直截了當。

stmt = (
    select(Product)
    .join(func.jsonb_each_text(Product.name).alias("e"), onclause=True)
    .filter(text("e.value = :target_value")
)

作為參考,這里是PostgreSQL 的 JSON 函數的文檔


完整的腳本演示:

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

metadata_obj = sa.MetaData()

t = sa.Table(
    "t73345077",
    metadata_obj,
    sa.Column("id", sa.Integer, primary_key=True),
    sa.Column("name", postgresql.JSONB),
)

engine = sa.create_engine(
    "postgresql+psycopg2://postgres:postgres@localhost:5432/postgres",
    echo=True,
    future=True,
)

metadata_obj.create_all(engine)

with engine.begin() as con:
    con.execute(
        sa.insert(t),
        [
            {"name": {"en": "goat", "fr": "chevre"}},
            {"name": {"en": "cow", "fr": "vache"}},
            {"name": {"en": "sheep", "fr": "mouton"}},
        ],
    )

with engine.connect() as con:
    r = con.execute(
        sa.select(t)
        .join(sa.func.jsonb_each_text(t.c.name).alias("e"), onclause=True)
        .filter(sa.text("e.value = :target_value"),
        dict(target_value="vache"),
    )
    print(r.all())  # gives [(2, {'en': 'cow', 'fr': 'vache'})]

查詢發出以下內容:

SELECT t73345077.id, t73345077.name 
FROM t73345077 JOIN jsonb_each_text(t73345077.name) AS e ON true 
WHERE e.value = 'vache'

對於后代,我保留的是我發現有效但未使用綁定參數的其他查詢,因此請使用上面的查詢。

sa.select(t).filter(
    sa.func.jsonb_path_exists(
        t.c.name,
        '$.keyvalue().value ?(@ == "vache")'
    )
)

sa.select(t).filter(sa.text("name @? '$.** ? (@ == \"vache\")';"))

暫無
暫無

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

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