使用Bookshelf修补程序为未引用的列设置默认值

时间:2018-03-13 03:18:10

标签: node.js postgresql bookshelf.js

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

我一直试图理解补丁参数在书架中的实际作用。似乎我可以用真或假传递它,并且行为没有任何变化。根据我的理解,虽然似乎传递一个假值应该更新所有列。

假设我有一个名为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

1 个答案:

答案 0 :(得分:2)

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

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

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

使用NULL

更新属性

现在,如果在update语句中显式传递属性值为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会生成一个查询,该查询将尝试更新所有在模型上设置的属性,而不仅仅是那些传递给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;
})