我正在嘗試使用 SQLAlchemy 更新 postgres 資料庫中 jsonb 欄位內的值。
一直在嘗試使用func.jsonb_set,但我不太清楚如何實作它。
使用如下表 ( test),我希望找到一種添加/編輯 json 資料的通用方法。
| ID | 資料 | 姓名 | |
|---|---|---|---|
| 1 | {“年齡”:44,“名字”:“巴里”,孩子”:[“baz”,“吉姆”]} | 巴里 | |
| 2 | {“年齡”:47,“姓名”:“戴夫”,“孩子”:[“杰夫”,“簡”]} | 戴夫 | |
以下適用于 postgres 的簡單更新。
UPDATE "test" SET "data"=jsonb_set("data"::jsonb, '{age}', '45')
WHERE "data"::json->>'name'='dave';
我可以用來update更新這樣的單個值:
testobj_res.update(
{
TestObj.data: cast(
cast(TestObj.data, JSONB).concat(func.jsonb_build_object("age", 45)),
JSON,
)
}
)
session.commit()
我希望能夠傳遞例如多個欄位的更新{"name": "barry", "age": 45, "height": 150}。
我嘗試使用func.jsonb_set添加更復雜的 json 結構而不是('age', 45)
testobj_res.first().data = func.jsonb_set(
TestObj.data.cast(JSONB),
("age", 45),
cast(TestObj.data, JSONB))
session.commit()
但我得到:
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedFunction) function jsonb_set(jsonb, record, jsonb) does not exist
LINE 1: UPDATE public.test SET data=jsonb_set(CAST(public.test.data ...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
完整示例代碼:
import os
from sqlalchemy.dialects.postgresql import JSON, JSONB
from sqlalchemy import func, cast
import sqlalchemy as sa
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import urllib
from dotenv import load_dotenv
load_dotenv()
user = urllib.parse.quote_plus(os.environ.get("DB_USER"))
passwd = urllib.parse.quote_plus(os.environ.get("DB_PW"))
DB_URL = "postgresql://{}:{}@{}:{}/{}".format(
user,
passwd,
os.environ.get("DB_HOST"),
os.environ.get("DB_PORT"),
os.environ.get("DB_NAME"),
)
engine = sa.create_engine(DB_URL)
Session = sessionmaker(bind=engine, autoflush=True)
session = Session()
Base = declarative_base()
class TestObj(Base):
__tablename__ = "test"
__table_args__ = {"autoload_with": engine, "schema": "public"}
testobj_res = session.query(TestObj).filter(TestObj.name == "dave")
testobj_res.first().data = func.jsonb_set(
TestObj.data.cast(JSONB),
("age", 45),
cast(TestObj.data, JSONB))
session.commit()
uj5u.com熱心網友回復:
這段代碼
testobj_res.first().data = func.jsonb_set(
TestObj.data.cast(JSONB),
("age", 45),
cast(TestObj.data, JSONB))
正在傳遞一個 JSONB 物件、記錄和另一個 JSONB 物件,jsonb_set但該函式需要一個 JSONB 物件、一個 JSONPath 字串和路徑的新值 JSONB *。
解('age', 45)包元組并洗掉最終的 JSONB 將產生所需的結果。
with Session.begin() as s:
testobj = s.scalar(sa.select(TestObj).limit(1))
testobj.data = sa.func.jsonb_set(
sa.cast(testobj.data, postgresql.JSONB),
'{age}',
sa.cast(42, postgresql.JSONB)
)
*還有一個可選的布爾 create-if-not-exists 引數,我們可以忽略它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/463035.html
標籤:PostgreSQL sqlalchemy jsonb
