【问题标题】:PostgreSQL jsonb update multiple nested fieldsPostgreSQL jsonb 更新多个嵌套字段
【发布时间】:2019-04-24 22:21:14
【问题描述】:

I 表在 postgresql 数据库中具有 id 字段和 jsonb 字段。 jsonb 的结构如下所示:

{
    "id": "some-id",
    "lastUpdated": "2018-10-24T10:36:29.174Z",
    "counters": {
        "counter1": 100,
        "counter2": 200
    }
}

我需要做的是更新lastModified 和其中一个计数器:

def update(id: String, counter: Option[String])

例如,如果我执行update("some-id", Some("counter2")),我需要将lastUpdated 作为当前日期时间,并将counter2 递增到201

我正在使用 ScalikeJDBC,这就是我目前的目标:

def update(id: String, counter: Option[String]): Option[ApiKey] = DB localTx { implicit session =>

val update =
  if(counter.isDefined)
    sqls"""'{"lastUpdated": ${DateTime.now()}, "counters": {'${counter.get}: COALESCE('counters'->>${counter.get},'0')::int'}'"""
  else
    sqls"""'{"lastUpdated": ${DateTime.now()}}'"""

sql"UPDATE apiKey SET content = content || $update WHERE id = $key".update().apply()
}

但我收到以下错误:

org.postgresql.util.PSQLException: The column index is out of range: 4, number of columns: 3

我尝试了其他方法,但无法成功。是否可以将其编写为单个查询?

这是一个坏掉的小提琴来帮助测试https://www.db-fiddle.com/f/bsteTUMXDGDSHp32fw2Zop/1

【问题讨论】:

标签: sql postgresql scala scalikejdbc


【解决方案1】:

我对 PostgreSQL 的 jsonb 类型了解不多,但似乎不可能在 JDBC PreparedStatement 中将所有内容作为绑定参数传递。我不得不说你可能不得不使用 SQLSyntax.createUnsafely 来绕过 PreparedStatement,如下所示:

def update(id: String, counter: Option[String]): Unit = DB localTx { implicit session =>
  val now = java.time.ZonedDateTime.now.toOffsetDateTime.toString
  val q: SQLSyntax = counter match { 
    case Some(c) => 
      val content: String =
        s"""
        jsonb_set(
            content || '{"lastUsed": "${now}"}',
            '{counters, $c}',
            (COALESCE(content->'counters'->>'$c','0')::int + 1)::text::jsonb
        )
        """
      SQLSyntax.createUnsafely(s"""
    UPDATE
        example
    SET
        content = ${content}
    WHERE
        id = '$id';
    """)
    case _ => 
      throw new RuntimeException
  }
  sql"$q".update.apply()
}
update("73c1fa11-bf2f-42c9-80fd-c70ac123fca9", Some("counter2"))

【讨论】:

    猜你喜欢
    • 2021-02-12
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    相关资源
    最近更新 更多