2016-03-09 2 views
3

У меня есть таблица, в которой есть один столбец, объявленный как json, и мне нужно обновить записи, добавив значение ключа в значение json.SqlAlchemy (Flask + Postgres): Как обновить только определенный атрибут 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}

, если я не хочу, чтобы запросить значение первых, изменение и обновление обратно.

Мне сложно определить, как это сделать в одном запросе, пожалуйста, помогите, спасибо!

ответ

0

Обратитесь к 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)) 
0

Таким образом, мы можем обновить новую пару ключ-значение в поле представлений.

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") 
0

если вы используете 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(...)) 
Смежные вопросы