2017-04-02 60 views
0

我有一個.itemId來自第三方,不是由我生成的。如何通過任意屬性在rethinkdb(reql)中插入文檔?

我需要在數據庫中查找它並更新或插入它,如果它不存在。

我一直使用從食譜這個例子嘗試:https://www.rethinkdb.com/docs/cookbook/javascript/#manipulating-documents

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`. 
    } 

res.changes如果文檔不存在,是不確定的,如果我搜索ID後,是不是在數據庫中。它從未插入。

有沒有一種方法可以簡化upsert()給定一個對象的任意屬性?

回答

1

在你應該做插入查詢,並在你的代碼分支子句中的「其他」的條款是沒有用的(查詢絕不會返回「空」這樣的項目不會被「創造」)

有有幾種方法可以解決這個問題: 最好的方法是使用itemId(或r.uuid(itemId))作爲主鍵,並使用衝突子句進行插入。

如果你不能 一種方法是去替代,如果不更換任何東西插入:

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() 

另一種方法是嘗試,看看是否存在和使用索引來UPSERT:

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」而不是「過濾器」。

,如果你有在同一時間獲得具有相同的itemId多個項目的高概率,這些方法也不能解決問題,解決這個問題,你需要創建一個不同的獨特表:

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字段

+0

'{... item,created_at:this.r.now()}, ^^^ SyntaxError:意外的標記...' – chovy

+0

既沒有示例工作。我改變了傳播到'Object.assign()'現在它會拋出一個錯誤關於缺少返回語句。 'ReqlDriverCompileError:匿名函數返回undefined。你忘了回報嗎?' – chovy

+0

什麼都不會更新。僅插入。 – chovy

相關問題