[英]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.