2013-11-20 35 views
1

我在使用MongoDB的NodeJS中開發演示應用程序,目前使用的模塊是Express和Mongoose。使用Mongoose從節點中插入,更新和從MongoDB中的複雜嵌入式集合中刪除

的主要思想是重拍一個PHP + MySQL app,其中MySQL數據庫包括三個表,在1:N關係:公司 - >現場>物品

的示例數據收集是這樣的:

[ 
{"id": 1,"name": "DemoCompanyOne", "fields":[ 
    {"id": 1, "location": "DemoLocationOne", "items":[ 
     {"_id": 1,"name": "DemoItemOne","price": 1500,"count": 16,"date": "2013-11-02 16:53:19"}, 
     {"_id": 2,"name": "DemoItemTwo","price": 890,"count": 211,"date": "2013-11-02 16:53:19"} 
    ]}, 
    {"id": 2, "location": "DemoLocationTwo", "items":[ 
     {"_id": 3,"name": "DemoItemThree","price": 9990,"count": 10,"date": "2013-11-02 19:12:40"}, 
     {"_id": 4,"name": "DemoItemFour","price": 2500,"count": 20,"date": "2013-11-02 19:12:42"} 
    ]} 
]}, 
{"id": 2,"name": "DemoCompanyTwo", "fields":[ 
    {"id": 3, "location": "DemoLocationThree", "items":[ 
     {"_id": 5,"name": "DemoItemFive","price": 79000,"count": 11,"date": "2013-11-02 16:56:13"}, 
     {"_id": 6,"name": "DemoItemSix","price": 649,"count": 8760,"date": "2013-11-02 16:56:13"}, 
     {"_id": 7,"name": "DemoItemSeven","price": 149,"count": 4320,"date": "2013-11-02 16:57:19"} 
    ]} 
]} 
] 

我在貓鼬製作模式,如:

var Schema = mongoose.Schema, ObjectId = Schema.ObjectId 

var Items = new Schema({ 
    _id: ObjectId, 
    name: String, 
    price: Number, 
    count: Number, 
    date: { type: Date, default: Date.now } 
}); 

var Field = new Schema({ 
    id: Number, 
    location: String, 
    items: [Items] 
}); 

var Company = new Schema({ 
    id: Number, 
    name: String, 
    Fields: [Field] 
}); 

var cmp = mongoose.model('company', Company, "company"); 
var flds = mongoose.model('fields', Field, "fields"); 
var itm = mongoose.model('items', Items, "items"); 

請注意,物品的_id在蒙戈改爲的ObjectId,因爲我希望這將幫助我HANDL e這些嵌入式收藏更好 - 它沒有。

我想插入項目到指定的位置,或增加選定項目的計數或刪除選定的項目。

的COMPANY_ID和FIELD_ID包含在URL,如:

app.post('/:company_id/:field_id', function(req, res) { ... }) 

這裏面的處理程序,我單獨的請求,如:

app.post('/:company_id/:field_id', function(req, res) { 
var company = req.params.company_id; 
var field = req.params.field_id; 
if (req.body.new != null) 
{ 
    cmp.findOne({}).where('id').equals(company).where('fields.id').equals(field).exec(function(err, comps) { 
     if (comps == null) 
     { res.render('error', {title: 'Error!', msg: 'No such field!'}); } 
     else 
     { 
      i=0; 
      while (i < comps.fields.length && comps.fields[i].id != field) 
      { i++; } 
      var r = new itm({"_id": "", "name": req.body.name, "price":req.body.price, "count":req.body.count}); 
      comps.fields[i].items.push(r); 
      comps.save(); 
     } 
    }); 
} 
else if (req.body.mod != null) 
{ 
    //... 
} 
else if (req.body.del != null) 
{ 
    //... 
} 
res.redirect('/'+company+'/'+field); 
}) 

正如你看到的,在項目加入我是使用線性搜索找到領域,在那裏我可以推新制作的項目...這是非常非常醜陋的,我敢肯定,必須有很多簡單的方法來做到這一點...

而且,關於增量重刑或刪除?我不想以同樣的方式...

而且,對於第四個問題:您如何看待ID?如何實施它們?我應該在任何地方使用ObjectIds,或者在任何地方都不需要?

任何幫助和想法表示讚賞!

回答

2

我的願景是使用嵌入式文檔,如果它們幾乎是靜態的。您的物體看起來活力給我,所以我建議你嘗試使用文件引用來代替:

var Schema = mongoose.Schema, ObjectId = Schema.ObjectId 

var Items = new Schema({ 
    _id: ObjectId, 
    name: String, 
    price: Number, 
    count: Number, 
    date: { type: Date, default: Date.now } 
    field: {type: Schema.Types.ObjectId, ref: 'Field'} 
}); 

var Field = new Schema({ 
    id: Number, 
    location: String, 
    company: {type: Schema.Types.ObjectId, ref: 'Company'} 
    items: [{type: Schema.Types.ObjectId, ref: 'Items'}] 
}); 

var Company = new Schema({ 
    id: Number, 
    name: String, 
    fields: [{type: Schema.Types.ObjectId, ref: 'Field'}] 
}); 

所以你一直喜歡在MySQL +讓孩子們引用作爲數組來填充快速家長參考。因此,您不必亂拼嵌套的文檔:

Field.findOne({_id: fieldid}).exec(function(err, field){...do whatever you need...}) 

此外,我不建議調用您的模型「項目」。用單數稱呼它,如「Item」。

+0

對於最近的答案感到抱歉:重新考慮和實施這個解決方案需要一些時間,但它工作正常,非常感謝你:放棄嵌入式文檔的想法應該是最後一個,但代碼很多**現在更簡單。 – Gardenee

+0

沒問題,但也請注意,嵌入式文檔的檢索速度要快於與參考文檔連接的文檔。因此,有時您可能想要使用它們,例如爲用戶保留不同的聯繫方式(電子郵件,推特,臉書,物理地址等) – igorpavlov

相關問題