![](/img/trans.png)
[英]SqlAlchemy + Postgres - query with @> ANY(ARRAY['["...]']::jsonb[])
[英]Postgres SQLAlchemy appending to existing jsonb record
我有一個帶有 jsonb 字段data
的 postgres 數據庫。
我希望能夠使用 sqlalchemy 附加到字段中的項目數組。
以表格為例:
ID | 數據 | 姓名 | |
---|---|---|---|
1 | [{“喬恩”:{“年齡”:4}},{“簡”:{“年齡”:7}}] | 保羅 | |
2 | [{“綠柱石”:{“年齡”:3}},{“維克多”:{“年齡”:9}}] | 戴夫 | |
要在 postgres 中執行此操作,我可以像這樣使用連接:
UPDATE "test" SET "data" = "data" || '[{"beryl": {"age": 3}}, {"victor": {"age": 9}}]' ::jsonb
WHERE "name"='paul';
給予:
ID | 數據 | 姓名 | |
---|---|---|---|
1 | [{“喬恩”:{“年齡”:4}},{“簡”:{“年齡”:7}},{“綠柱石”:{“年齡”:3}},{“維克多”:{“年齡”:9}}] | 保羅 | |
我試過在 sqlalchemy 中使用 jsonb_insert,但我不清楚如何設置路徑。
我不想在特定鍵處添加數組,但想添加到現有數組中。
編輯
以下將另一個數組嵌套在我現有的數組中,即['A', 'B']
的形式變為['A','B',['C','D']]
。 我希望這是['A','B','C','D']
func.jsonb_insert(
cast(TestObj.data, JSONB), "{-1}", cast(new_records, JSONB), True
)
編輯 2
使用synchronize_session="fetch"
並在循環中添加記錄是可行的,但我不確定它對於很多記錄是否非常有效。
感謝任何關於如何改進這一點的想法。
for rec in new_records:
session.query(TestObj).filter(TestObj.name == "paul").update(
{
"data": func.jsonb_insert(
cast(TestObj.data, JSONB), "{-1}", cast(rec, JSONB), True
)
},
synchronize_session="fetch",
)
完整示例代碼:
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 sqlalchemy.dialects import postgresql
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"}
initial_data = [
{
"jon": {"age": 4},
},
{"jane": {"age": 7}},
]
newentry = {"data": initial_data, "name": "paul"}
stmt = postgresql.insert(TestObj).values(newentry)
result = session.execute(stmt)
session.commit()
new_records = [{"bob": {"age": 10}}, {"billy": {"age": 10}}]
for rec in new_records:
session.query(TestObj).filter(TestObj.name == "paul").update(
{
"data": func.jsonb_insert(
cast(TestObj.data, JSONB), "{-1}", cast(rec, JSONB), True
)
},
synchronize_session="fetch",
)
session.commit()
在 SQLAlchemy 中,SQL ||
運算符是 Python +
運算符。 我在這個 Github issue中找到了這些信息。
附加到您的示例的現有 JSONB 數組應該類似於(未經測試):
new_records = [{"bob": {"age": 10}}, {"billy": {"age": 10}}]
stmt = (
sa.update(TestObj)
.filter_by(name="paul")
.values(data=TestObj.data + new_records) # concatenate existing data with new records
)
session.execute(stmt)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.