首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过任意属性在rethinkdb (reql)中插入文档?

如何通过任意属性在rethinkdb (reql)中插入文档?
EN

Stack Overflow用户
提问于 2017-04-02 05:41:58
回答 1查看 1K关注 0票数 1

我有一个来自第三方的.itemId,而不是由我生成的。

我需要在db中查找它,如果不存在更新或插入它。

我尝试使用菜谱中的这个例子:https://www.rethinkdb.com/docs/cookbook/javascript/#manipulating-documents

代码语言:javascript
复制
  const res = await this.r.table('products').filter({itemId: item.itemId})
    .limit(1)
    .replace(doc => {
      return this.r.branch(
        doc.eq(null),
        this.r.expr(item).merge({created_at: this.r.now()}),
        doc.merge(item).merge({updated_at: this.r.now()})
      )
    }, {
      returnChanges: true
    }).run(this.conn);


  if (res.replaced) {
    return res.changes[0].new_val;
  } else {
    return item; // doc was never inserted as everything in `res` is `0`.
  }

如果文档不存在,并且在id不在数据库后搜索id,则res.changes是未定义的。从来没插进去过。

是否有一种方法可以简化给定对象的任意属性的upsert()命令?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-02 06:18:40

在“否则”子句中,您应该执行insert查询,并且代码中的分支子句是无用的(查询永远不会返回"null“,这样就不会”创建“项)

有几种方法可以解决这个问题:最好的方法是使用itemId (或r.uuid(itemId))作为主键,并使用冲突子句进行插入。

如果不能,一种方法是尝试并替换,如果没有替换任何内容,请插入:

代码语言:javascript
复制
this.r.table('products').filter({itemId: item.itemId})
.limit(1)
.replace(
    doc => doc.merge(item).merge({updated_at: this.r.now()}), 
    { returnChanges: true }
)
.do(res => res('replaced').eq(1).branch(
    res,
    r.table('products').insert(
        { ...item, created_at: this.r.now()}, 
        { returnChanges: true }
    )
))
.run()

另一种方法是尝试查看是否存在并使用索引重新插入:

代码语言:javascript
复制
this.r.table('products').filter({itemId: item.itemId})
.nth(0)
.default(null)
.do(res => 
    r.table('products').insert(
        { 
          ...item, 
          id: res('id').default(r.uuid()), 
          created_at: this.r.now()
        }, 
        { 
            returnChanges: true,
            conflict: (id, old, new) => 
                old.merge(item).merge({updated_at: this.r.now()})
        }
    )
))
.run()

另外,如果您需要它来执行,我建议在itemId上创建一个辅助索引,并使用"getAll“而不是"filter”。

如果您同时使用同一个itemId获得多个项的可能性很高,那么这些方法不会有帮助,要解决这个问题,您需要创建一个不同的唯一表:

代码语言:javascript
复制
r.table('products_itemId')
 .insert(
    {itemId: item.itemId, id: r.uuid()},
    { returnChanges: true, conflict: (id, old, new) => old }
 )
 .do(res => 
     r.table('products').insert(
        { 
          ...item, 
          id: res('new_val')('id'),
          created_at: this.r.now()
        }, 
        { 
            returnChanges: true,
            conflict: (id, old, new) => 
                old.merge(item).merge({updated_at: this.r.now()})
        }
    )
))
.run()

注意,您必须手动维护对itemId字段的删除和更新

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43165018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档