我看到這個問題和給出的答案,但我不認爲它真的解釋了你問的問題,所以我認爲這裏值得一提。
正如在提供的模式中所演示的,「topics」屬性是一個「引用數組」,它基本上意味着它將對位於另一個集合中的文檔持有「引用」(或基本上爲ObjectId
值) 。正如你應該知道的那樣,貓鼬的「模式」定義是將它與該對象所在的「關聯」模型聯繫起來的。
提出的問題是「我推動對象,還是我推動_id
價值」,這本身就引發了一些關於「你真的想在這裏做什麼?」的問題。
等待最後,採取下面的代碼示例(假定模型和模式都被定義):
var project = new Project({ "name": "something" });
var topic = new Topic({ "name": "something" });
project.topics.push(topic); // this actually just adds _id since it's a ref
// More code to save topic and project in their colllections
所以按照在代碼中有註釋,貓鼬實際上只增加了「_id」值成父文件,即使你問它「推」整個「對象」。它只是通過模型接口提供的「這就是你要做的」。真的不難做到,但只是讓你瞭解底層機制。
您也可以從創建的對象中替換「只使用_id
的值」(在爲了安全起見而保存得最好之後)並通過類似的方法將其添加到數組中。這是大致相同的結果:
var project = new Project({ "name": "something" });
// Yes we saved the Project object, but later...
var topic = new Topic({ "name": "something" });
topic.save(function(err,topic) {
if (err) throw (err): // or better handling
project.topics.push(topic._id); // explicit _id
});
這種方法是一切都很好,當然,前提是通過某種形式或其他你確實有在加工時的「內存中的對象」兩個Project
和Topic
與適當的數據。另一方面,讓我們假設Project
表示一個位於集合中的對象,雖然您知道它是_id
值或其他表示屬性的「唯一」,但該對象數據實際上並未從數據庫中通過.findOne()
操作類型或類似。
然後讓我們假設您沒有駐留在內存中的Project
模型數據。那麼如何添加你的新話題?
這是MongoDB的本地運營商發揮作用的地方。尤其是,存在$push
這當然是類似於JavaScript中的.push()
數組運算符,但與特定的「服務器端」行動。
如前所述,你沒有加載Project
模型數據,但你希望通過「推」來修改存儲特定Project
項目所需Topic
對象的東西通過它您Project
對象的集合中定義的標識符:
var topic = new Topic({ "name": "something" });
topic.save(function(err,topic) {
if (err) throw err; // or much better handling
Project.update(
{ "_id": projectId },
{ "$push": {
"topics": topic._id
}},
function(err,numAffected) {
// and handle responses here
}
);
})
「更新」機制可以.findOneAndUpdate()
甚至.findByIdAndUpdate()
爲您找到合適的(這些方法都在默認情況下,其中.update()
沒有返回修飾的對象)要實現如下的操作的結果是什麼。
與以前的方法的主要區別是,由於Project
要修改的對象不駐留在您的應用程序代碼的內存中,因此您可以使用這些方法在服務器上修改它。這可能是一件「好事」,因爲您不需要需要來「加載」該數據以進行修改。 MongoDB運營商允許您在不加載的情況下爲$push
陣列內容。
這種做法是實際上可以「同時更新」以高交易系統的最好的辦法。原因是,有「不保證」,在應用程序中的.findOne()
或類似的操作,並最終.save()
行動,「沒有數據已改變」上發生的那些動作之間的服務器存儲的修改之間。
$push
$push
運算符「確保」在執行時,服務器上修改的數據保持「原樣」,當然還有添加到數組中的新數據。
還有其它的一些明顯的事情是,由於操作使用本機MongoDB的操作來實現這一效率芻議,貓鼬架構規則bybassed。所以,你當然不能只是「推」了整個「主題」對象入陣,當然沒有與存儲的「整」主題對象結束了的:
Project.update(
{ "_id": projectId },
{ "$push": {
"topics": topic // Oops, now that would store the whole object!
}},
function(err,numAffected) {
// and handle responses here
}
);
也就是說本質的區別,「加入一個對象引用「到一個數組並且」添加一個'對象到一個數組「。這取決於您使用的方法和您實際選擇的「效率」方法。
希望這對自己和那些可能偶然發現您提出的同一主題的其他人有用。
優秀的答案。正是我需要的。謝謝澄清! –
嗨基拉。你可以加入這個聊天室嗎? http://chat.stackoverflow.com/rooms/95345/ –
@BlakesSeven你能不能請給我你的電子郵件地址?無論是在這裏還是在我的電子郵件地址:[email protected] - 我想邀請你參加我創建的MongoDB Slack團隊。 –