RethinkDB:条件追加启动(仅当特定字段匹配时)

RethinkDB: conditional upsert (only if particular fields are matched)?

本文关键字:字段 条件 追加 启动 RethinkDB      更新时间:2024-06-29

我知道rethinkDB的insert()有一个upstart选项。例如,来自文档:

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'}记录?

简而言之:我如何才能追加销售,以便只有在特定字段匹配的情况下才能更新现有记录?

编辑:看起来这是用.replacement():完成的

以下是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)

您的第二个代码块有两个错误。

首先,mergeOrCreate函数不起作用,因为if语句是在客户端求值的。您必须使用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);

请注意,由于此查询依赖于多个文档,因此它不是原子查询。