2015-06-24 25 views
2

我是Mongoose的新手,並讓我的頭部繞着人羣。我有架構,看起來像...將一個對象添加到Mongoose模型中的人口

var ProjectSchema = new Schema({ 
    name: { 
     type: String, 
     default: '', 
     required: 'Please fill Project name', 
     trim: true 
    }, 
    created: { 
     type: Date, 
     default: Date.now 
    }, 
    topics: [{ 
     type: Schema.ObjectId, 
     ref: 'Topic' 
    }] 
}); 

當我查詢項目我使用.populate('主題'),它工作正常。當項目填充時,主題屬性保存實際對象而不是引用。

P.S.該主題沒有項目參考(我發現很難在MongoDB中保持相互關係)。

我的問題是:當我想要添加一個主題對象到一個項目。我是否添加ObjectId或對象本身?

回答

3

我看到這個問題和給出的答案,但我不認爲它真的解釋了你問的問題,所以我認爲這裏值得一提。

正如在提供的模式中所演示的,「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 
}); 

這種方法是一切都很好,當然,前提是通過某種形式或其他你確實有在加工時的「內存中的對象」兩個ProjectTopic與適當的數據。另一方面,讓我們假設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 
     } 
    ); 

也就是說本質的區別,「加入一個對象引用「到一個數組並且」添加一個'對象到一個數組「。這取決於您使用的方法和您實際選擇的「效率」方法。

希望這對自己和那些可能偶然發現您提出的同一主題的其他人有用。

+0

優秀的答案。正是我需要的。謝謝澄清! –

+0

嗨基拉。你可以加入這個聊天室嗎? http://chat.stackoverflow.com/rooms/95345/ –

+0

@BlakesSeven你能不能請給我你的電子郵件地址?無論是在這裏還是在我的電子郵件地址:[email protected] - 我想邀請你參加我創建的MongoDB Slack團隊。 –

1

你只需要保存的ObjectId如果主題模式有一個項目編號爲節省裁判對其他文檔的工作方式相同,您通常保存的特性,只是指定_id值:

var topicSchema = Schema({ 
    _author : { type: Schema.ObjectId, ref: 'Project' }, 
    title : String  
}); 

var Topic = mongoose.model('Topic', topicSchema); 
var Project = mongoose.model('Project', projectSchema); 

var my_project = new Project({ name: 'Test Project' }); 

my_project.save(function (err) { 
    if (err) return handleError(err); 

    var topic1 = new Topic({ 
     title: "My Topic", 
     _author: my_project._id // assign the _id from the project 
    }); 

    topic1.save(function (err) { 
     if (err) return handleError(err); 
     // thats it! 
    }); 
}); 

參考docs瞭解更多詳情。


- 編輯 -

如果主題模式不具備項目裁判,那麼你需要推對象本身:

var Topic = mongoose.model('Topic', topicSchema); 
var Project = mongoose.model('Project', projectSchema); 

var my_project = new Project({ name: 'Test Project' }); 
var topic1 = new Topic({ 
    title: "My Topic"  
}); 

my_project.stories.push(topic1); 
my_project.save(callback); 
+1

你在這裏完全相反。在存儲主題列表到項目時,您正在存儲主題中的項目引用。問題是,在前端,「填充」項目帶有嵌入的完整主題實例。你是否暗示我應該在包含對象的列表中添加Id? –

+1

@MikeM在'Topic'模式也有'Project'參考的假設下回答。你能用實際的主題模式更新你的問題嗎? – chridam

相關問題