我知道rethinkDB's insert()有一个upsert选项。例如,从文档中:
rethinkdb.table('marvel').insert(
{ superhero: 'Iron Man', superpower: 'Arc Reactor' },
{upsert: true, return_vals: true}
).run(conn, callback)
但是,说可能是,是超能力不正确或已过时的
{superhero: 'Iron Man'}
的现有记录,我想插入{ superhero: 'Iron Man', superpower: 'Arc Reactor' }
还是更新任何现有的{superhero: 'Iron Man'}
记录?简而言之:我该如何增补,以便仅在匹配特定字段的情况下才更新现有记录?
编辑:似乎是用.replace()完成的:
这是the important bit from the replace() docs:
我不确定'point-replace'是什么意思-但我认为这只是意味着替换。
var latestDoc = { superhero: 'Iron Man', superpower: 'Arc Reactor' }
var mergeOrCreate = function(existingDoc) {
if ( existingDoc ) {
return existingDoc.merge(latestDoc)
} else {
return latestDoc
}
}
rethinkdb.table('marvel')
.filter({ superhero: 'Iron Man'})
.replace(mergeOrCreate),
).run(conn, callback)
但是,在测试中,'mergeOrCreate'函数被赋予了另一个函数,而不是实际的文档或游标作为参数。
最佳答案
您的第一个代码块是您第一个问题的答案。但是,它假定superhero
是表的主键。
您可以在创建表时设置表的主键:
r.tableCreate('marvel', {primaryKey: 'superhero'}).run(conn, cb)
您的第二个代码块有两个错误。
首先,由于
if
语句是在客户端评估的,所以mergeOrCreate函数不起作用。您必须使用r.branch
来创建if
语句的等效项:var mergeOrCreate = function(existingDoc) {
return r.branch(existingDoc, /* if */
existingDoc.merge(latestDoc), /* then */
latestDoc) /* else */
}
其次,
get
不支持与filter
相同的语法。它的参数应该是主键的值。如果主键是superhero
,则:r.table('marvel')
.get('Iron Man')
最后,如果
superhero
不是主键,则必须编写另一种查询。可能有零个,一个或多个具有相同superhero
的文档。这是一种编写方法:r.table('marvel')
.insert(
r.table('marvel')
.filter({ superhero: 'Iron Man' })
.coerceTo('array')
.do(function(docs){
return r.branch(
docs,
docs.merge(latestDoc),
latestDoc)
}),
{ upsert: true })
.run(conn, cb);
请注意,因为此查询依赖于多个文档,所以它不是原子的。