- 我有一个名为
Radio
的模型,其中包含一个应用分配的字符串主键,名为serial
,并且为了本示例,包含两个名为example1
和example2
的字段。我在模型定义中使用idAttribute: 'serial'
指定了自定义ID。 - 我正在尝试使用Bookshelf执行upsert(而不是直接使用Knex,在我的实际应用程序中,该查询变得相当复杂)。
- 我已经使插入情况工作,但似乎无法使更新情况工作。
- 为简单起见,我现在不关心事务或原子性。我满意于让一个简单的select → insert/update工作。
特别是在这个例子中:
- 在插入时设置
example1
和example2
。 - 在更新时设置
example1
并保持example2
不变。
我在书架模型中有这样一个类(即“静态”)方法,类似于以下内容(“info”具有“序列号”,“示例1”和“示例2”字段):
insertOrUpdate: function (info) {
return new Radio({'serial':info.serial}).fetch().then(function (model) {
if (model) {
model.set('example1', info.example1);
return model.save({}, {
method: 'update',
patch: true
})
} else {
return new Radio({
serial: info.serial,
example1: info.example1,
example2: info.example2
}).save({}, {
method: 'insert'
})
}
}).then(function (model) {
console.log("SUCCESS");
}).catch(function (err) {
console.log("ERROR", err);
});
}
示例调用:
Radio.insertOrUpdate({
serial: ...,
example1: ...,
example2: ...
})
我在这里遇到的问题是,虽然“插入”情况可以正常工作,但“更新”情况会失败并显示以下错误信息:
ERROR { Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where `serial` = '123223'' at line 1
当Knex调试打开时,显然查询语句缺少
set
子句。update `radios` set where `serial` = ?
现在,我正在关注
fetch
和save
的书架文档,并且我想知道我是否走错了方向。我知道我在错误地使用API,但我无法弄清楚。为了使其半工作状态,我注意到了一些奇怪的事情/必须要做的事情。
我不理解
save
的第一个参数是什么意思。如果save
是Model
的一个静态方法,那么它对我来说就有意义了,但事实并非如此。它是一个实例方法,你已经可以在Model
构造函数中传递属性(例如,new X(a:1).save({a:2})
是什么意思?),并且你已经可以在保存之前使用set
设置属性。所以我无法理解这个参数。我必须传递{}
作为占位符,以便让我指定选项。有这个
forge
的东西,但我不确定它的目的是什么,因为你已经可以在Model
构造函数中传递属性了(除非作者发现X.forge({a:1})
与new X({a:1})
相比有一些好处...?)。我发现我必须明确指定保存方法,因为似乎存在一个Bookshelf怪癖:Bookshelf基于
isNew()
选择方法,但当你将id传递给模型构造函数时,isNew()
总是true
,在应用程序分配ID的情况下,你必须这样做。因此,对于应用程序分配的ID,Bookshelf将始终执行“插入”,因为它始终认为模型是“新的”。所以你必须强制方法为“更新”...这只会增加我的Bookshelf困惑。
无论如何,我该怎样才能做好这个?我该如何让这个插入和更新工作?
更重要的是,这在哪里有记录?我真诚地认为它在某个地方被清晰地记录下来了,只是我现在看不到树林了,所以比起直接回答,我更需要一些文档上的指引,因为我确实需要搞清楚这个。我已经花了很多时间在书架上,而不是真正的开发,以至于我几乎希望我一开始就坚持使用直接的SQL查询。
.save({}, options)
,您明确地向 Bookshelf 发送了一个空的更新对象。您可以尝试使用null
代替吗?即.save(null, options)
。 - Eric Ly