【问题标题】:SqlAlchemy(Flask+Postgres) : How to update only a specific attribute of a json field?SqlAlchemy(Flask+Postgres):如何仅更新 json 字段的特定属性?
【发布时间】:2016-06-24 04:42:41
【问题描述】:

我有一个表,其中有一列声明为 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)

控制器

@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>))

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

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

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

我很难弄清楚如何在单个查询中执行此操作,请帮助,谢谢!

【问题讨论】:

  • 更新整个 json 字段对我有用。检索 json,对其进行修改并保存回来。
  • 仅供我理解。你能解释一下你是如何创建users 的吗?

标签: python json postgresql sqlalchemy flask-sqlalchemy


【解决方案1】:

如果你使用JSONB,你可以使用jsonb_set函数

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

如果您是从其他列插入

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

【讨论】:

  • 感谢这个有用的答案!我正在尝试使用另一列更新 jsonb,但是如您所描述的那样转换为 JSONB 不适用于字符串。我总是收到InvalidTextRepresentation 错误。我猜是因为需要多个引号'"jsonb-value"'。知道如何正确转换值吗?谢谢!
  • cast('"'+other_table.c.other_column+'"', JSONB) 帮了我大忙。
【解决方案2】:

请参阅this answer 了解如何在 SQL 中执行此操作。

在 Python 中做同样的事情(使用 PostgreSQL 9.5):

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

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

update().where(...)\
    .values(views=func.json_object_set_key(u.c.views, '1002', 1))

【讨论】:

    【解决方案3】:

    这样我们可以在视图字段中更新新的键值对。

    users.query.filter(users.c.loginId==loginId).update({users.data: cast(
            cast(users.data, JSONB).concat(func.jsonb_build_object('1002', 1)), JSON)}, synchronize_session="fetch")
    

    【讨论】:

      猜你喜欢
      • 2019-10-06
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 2020-07-11
      • 2021-06-05
      相关资源
      最近更新 更多