使用 Bookshelf 补丁为未引用的列设置默认值

Use Bookshelf patch to set default values for unreferenced columns

我的目标是:检查 postgres 数据库中是否存在条目。如果条目存在,请使用我提供的数据更新条目中的某些列,同时将未引用的列值设置为 null(或默认值)。否则只需保存一个新条目。

我一直在努力了解补丁参数在书架中的实际作用。看来我可以用 true 或 false 传递它,并且行为没有任何变化。据我了解,传递一个假值似乎应该更新所有列。

假设我有一个名为 table 的 table,列为 user_id, timestamp, property1, property2。我想用下面的代码实现的应该用提供的值更新条目,但将 property2 设置为默认值。

Models.table
  .where({user_id: session.userId})
  .fetch()
  .then(tableEntry => {
      let newTableEntry = {
          user_id: session.userId,
          timestamp: new Date(),
          property1: "a string"
      }
      if (tableEntry){
          return tableEntry.save(newTableEntry, {patch: false})
      }
      else {
          return new Models.table().save(newTableEntry)
      }
  })

我能做到这一点的唯一方法似乎是将其他列明确设置为 null

为什么补丁选项似乎没有什么区别

patch 选项中使用 truefalse 时没有看到任何差异的原因是因为您已经传递了大部分属性以进行更新保存调用(user_idtimestampproperty1),我假设 property2 已经在数据库中设置了默认值。因此,patch 只会更新这 3 列,但由于您没有传递第四列,因此它将保留其当前值。如果您不使用 patch 选项,则更新查询将使用已在模型上设置的 property2 的值,该值与数据库中已有的值相同,因此 patch在这种情况下选项几乎没用。

补丁的主要区别在于生成的查询效率更高。

使用 NULL

更新属性

现在,如果您在更新语句中显式将属性值作为 null 传递,它将在数据库中将其设置为 NULL,但如果您不包含该属性,则它不会未设置:

tableEntry.save({timestamp: new Date(), property1: null}, {patch: true})
// UPDATE my_table SET timestamp = '2018...', property1 = NULL WHERE user_id = 1

tableEntry.save({timestamp: new Date()}, {patch: true})
// UPDATE my_table SET timestamp = '2018...' WHERE user_id = 1

正在用 DEFAULT 值更新属性

Bookshelf 目前不支持该功能。如果需要,您可以为此打开 new feature request

然而,有一个类似的功能允许您在更新语句中使用一些默认值,但您必须自己提供这些值,而不依赖数据库为您做这些:

tableEntry.save({timestamp: new Date()}, {patch: true, defaults: true})

这要求模型具有具有默认值的属性:

var MyModel = bookshelf.Model.extend({
  defaults: {property1: 'foo', property2: 'bar'},
  tableName: 'my_table'
})

不幸的是,此功能没有正确记录,但它应该按预期工作。

何时使用补丁

当您像以前一样从数据库中获取模型时,通常会使用此方法,但您只对更新模型的某些属性感兴趣。这很有用,因为默认情况下 Bookshelf 将生成一个查询,该查询将尝试更新 all 在模型上设置的属性,而不仅仅是那些传递给 save:

的属性
Models.table.forge({user_id: 1}).fetch().then(tableEntry => {
  // tableEntry has all attributes set with a value
  return tableEntry.save()
  // This will generate a query like:
  // UPDATE my_table SET user_id = 1, timestamp = '2018...',
  //        property1 = 'foo', property2 = 'bar', WHERE user_id = 1;
})

使用补丁:

Models.table.forge({user_id: 1}).fetch().then(tableEntry => {
  // tableEntry has all attributes set with a value
  return tableEntry.save({property2: 'something'}, {patch: true})
  // This will generate a query like:
  // UPDATE my_table SET property2 = 'something', WHERE user_id = 1;
})