我正在尝试更新 users 表中的列,列类型为json。
列名称是测试。
该列由一个对象默认值组成,例如是
{a: "text", b: 0}
如何更新对象键b而不更改整个列
我正在使用的代码是
knexDb('users').where({
  email: email
})
.update({
  test: { b: 1 }
})
Run Code Online (Sandbox Code Playgroud)
第二种解决方案
knexDb('users').where({
  email: email
})
.update({
  test: knexDb.raw(`jsonb_set(??, '{b}', ?)`, ['test', 1])
})
Run Code Online (Sandbox Code Playgroud)
第一个解决方案更改整个列单元格,并且测试将仅{ b: 1 }
第二个解决方案不起作用,会出现错误
函数 jsonb_set(json, 未知, 未知) 不存在
预期结果
就是设法只更新对象中的某个键值而不更改整个对象。
聚苯乙烯
我还想更新一个由像上面这样的对象组成的数组。
[{a: "text", b: 0}, {c: "another-text", d: 0}]
如果我在 kenxjs 中使用上面的代码,它会将整个数组更新为仅{b: 1}
PS经过大量搜索后发现,为了使其工作,我需要将列类型设置为 jsonb,以便上面的 jsonb_set() 工作
但现在我面临另一个问题
如何使用 jsonb_set 更新多个密钥
knexDb('users').where({
      email: email
    })
    .update({
      test: knexDb.raw(`jsonb_set(??, '{b}', ?)`, ['test', 1]),
      test: knexDb.raw(`jsonb_set(??, '{a}', ?)`, ['test', "another-text"]),
    })
Run Code Online (Sandbox Code Playgroud)
第一个查询键 b 现在没有更新,实际上除了最后一个查询键之外所有更新都不起作用a,所以有人可以解释为什么吗?
你的问题是你正在覆盖test. 你传入的update是一个 JS 对象(docs)。您不能拥有多个具有相同值的键(文档)。您必须执行类似这样的操作,其中使用所有原始 SQL 作为 的值创建 1 个长字符串test。
knexDb('users').where({
      email: email
    })
    .update({
      test: knexDb.raw(`
          jsonb_set(??, '{a}', ?)
          jsonb_set(??, '{b}', ?)
        `,
        ['test', "another-text", 'test', 1])
    })
Run Code Online (Sandbox Code Playgroud)
可能存在更好的选择 - 如果您必须对几列执行此操作,则该选择将更具可读性,类似于我在下面包含的内容。在此示例中,包含 的列jsonb称为json。
const updateUser = async (email, a, b) => {
  const user = await knexDb('users')
    .where({ email })
    .first();
  user.json.a = a;
  user.json.b = b;
  const updatedUser = await knexDb('users')
    .where({ email })
    .update(user)
    .returning('*');
  return updatedUser;
}
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           5267 次  |  
        
|   最近记录:  |