2016-07-10 84 views
0

下面我有一個假設的模型,用節點MongoDB的原生驅動MongoDB的更新家長和父親的父親和這麼來回

A01有着直接的子(A03),孫子(A04)和一個偉大的孫子( A05):A01 - > A03 - > A04 - > A05

A02有着直接的子(A06)

如果一個孩子得到一個分數,所有的家長得到它。例如,如果我給出分數A05,所有的家長(A01至A04)將得到一個分數

[{ 
    _id: 'A01', 
    p_id: '', // parent _id 
    score: 0, 
}, { 
    _id: 'A02', 
    p_id: '', 
    score: 0, 
}, { 
    _id: 'A03', 
    p_id: 'A01', 
    score: 0, 
}, { 
    _id: 'A04', 
    p_id: 'A03', 
    score: 0, 
}, { 
    _id: 'A05', 
    p_id: 'A04', 
    score: 0, 
}, { 
    _id: 'A06', 
    p_id: '', 
    score: 0, 
}, 
{ 
    _id: 'A07', 
    p_id: 'A02', 
    score: 0, 
}, { 
    _id: 'A08', 
    p_id: '', 
    score: 0, 
}] 


// my naive implementation 
function updateScore({ _id, score }) { 
    return db.collection 
    .findOneAndUpdate({ _id: }, { $inc: { score } }) 
    .then(function ({ value }) { 
     if (value && value.p_id) return updateScore({ _id: value.p_id, score }) // recursively update the parent score 
     return Promise.resolve() // if no parent is found 
    }) 
    .catch(function (error) {}) 
} 

updateScore({ _id: 'A05', score: 1 }) 

在我幼稚的功能,應用程序發送一個查詢(由1增加A05的得分)到Mongo服務器。 mongo服務器接收查詢並運行它,將一些數據返回給應用程序。應用程序檢查是否存在父_id,如果是,則會將查詢發送到mongo服務器。該過程重複,直到沒有父_id。

我的想法是,應用程序和mongo服務器之間來回發送數據並不是最好的選擇,因爲(1)如果mongo服務器是遠程託管的延遲,(2)如果數據很大,則會消耗帶寬。

我看了看bulkWrite,但是當它不知道的p_id

我看着running js file in mongo shell這表明它不能更新「連接快速低延遲」和Store a JavaScript Function on the Server,但它說:「別存儲應用程序邏輯在數據庫中「。並不一定是「快」。

所以問題:在這種情況下,什麼是「最好」的方式,更新所有父母的分數。

回答

1

我會考慮...

  • 利用圖形數據庫,而不是原生地允許這些類型的更新。
  • 添加一些其他字段,如「family_id」,以便您可以執行一次多重更新:db.collection.update({"family_id": "123"}, { $inc: { score } })
  • 與上面類似,存儲每個孩子的父母列表。這可以讓你下到兩個更新(查找和更新孩子;更新所有的父母)。

在任何情況下,你也可以考慮更新家長的分數,但是當你需要計算分數照顧孩子而總結。通過一些模式更改,您可以使用聚合管道進行此操作。如果您經常增加並且很少查詢,這將會更加高效。