【问题标题】:RethinkDB: conditional upsert (only if particular fields are matched)?RethinkDB:​​条件更新(仅当特定字段匹配时)?
【发布时间】:2013-12-11 12:07:17
【问题描述】:

我知道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'} 记录? p>

简而言之:我怎样才能 upsert 以便仅在匹配特定字段时更新现有记录?

编辑:似乎这是用 .replace() 完成的:

这里是the important bit from the replace() docs:

如果您对键进行点替换,则可以插入新文档 不在表格中

我不确定“点替换”是什么意思 - 但我认为它只是意味着替换。

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”函数被赋予了另一个函数,而不是实际的文档或游标,作为参数。

【问题讨论】:

    标签: javascript node.js rethinkdb


    【解决方案1】:

    您的第一个代码块是您第一个问题的答案。但是,它假定 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);
    

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

    【讨论】:

    • 谢谢!你介意我问你几个问题吗?是否应该始终使用 insert 和 upsert 选项来完成条件更新插入?
    • 不,就像您注意到的那样,也可以使用替换。点替换是 get 之后的替换。
    • 谢谢!有没有办法实现原子条件更新?例如,如果任何文档匹配,则更新第一个匹配,如果不匹配,则创建文档?
    • 另外:插入还是替换更适合这个目的?抱歉所有问题,但我在文档中找不到任何指针。
    • 没有。 RethinkDB 中的原子操作只能依赖和修改单个文档。
    猜你喜欢
    • 2021-06-29
    • 1970-01-01
    • 2021-10-22
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多