SqlAlchemy(Flask+Postgres):如何仅更新 json 字段的特定属性?

moa*_*lee 6 python postgresql json sqlalchemy flask-sqlalchemy

我有一个表,其中一列声明为 json,我需要通过向 json 值添加键值来更新记录。

模型

class User(db.Model):

    __tablename__ = 'users'

    loginId         = db.Column(db.String(128),  nullable=False, primary_key=True)
    _password       = db.Column(db.String(128),  nullable=True)
    views           = db.Column(JSON,         nullable=True)
Run Code Online (Sandbox Code Playgroud)

控制器

@mod_event.route('/view', methods=['POST'])
def view():
    try:
        params = request.json
        loginId = params['dream']['loginId']
        users.update().\
            where(users.c.loginId==loginId).\
            values(views=<query>))
Run Code Online (Sandbox Code Playgroud)

假设当前值为views{'1001' : 1} 如果必须将查询views更新为 -

  • {'1001':2}
  • {'1001':1,'1002':1}

如果我不想先查询该值,请更改并更新回来。

我很难在一个查询中弄清楚如何做到这一点,请帮忙,谢谢!

Deo*_*ung 6

如果您正在使用JSONB,则可以使用该jsonb_set功能

(table
 .update()
 .values(views=func.jsonb_set(table.c.views,
                              '{%s}' % '1002',
                              1))
 .where(...))
Run Code Online (Sandbox Code Playgroud)

如果您从其他列插入

(table
 .update()
 .values(views=func.jsonb_set(table.c.views,
                              '{%s}' % '1002',
                             other_table.c.other_column.cast(String).cast(JSONB)))
 .where(...))
Run Code Online (Sandbox Code Playgroud)


uni*_*rio 1

请参阅此答案以了解如何在 SQL 中执行此操作。

要在 Python 中执行相同的操作(使用 PostgreSQL 9.5):

update().where(...)\
    .values(views=cast(cast(u.c.views, JSONB)
                       .concat(func.jsonb_build_object('1002', 1)), JSON)
Run Code Online (Sandbox Code Playgroud)

对于 PostgreSQL 9.3+,您必须首先在 PostgreSQL 中创建该函数,然后:

update().where(...)\
    .values(views=func.json_object_set_key(u.c.views, '1002', 1))
Run Code Online (Sandbox Code Playgroud)