使用Mongoose从节点插入,更新和从MongoDB中的复杂embedded式集合中移除

我在使用MongoDB的NodeJS中开发一个演示程序,目前使用的模块是Express和Mongoose。

主要想法是重build一个PHP + MySQL应用程序,其中MySQL数据库由三个表组成,数据库为1:N关系:Company-> Field-> Item

示例datacollection看起来像:

[ {"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"} ]} ]} ] 

我已经在mongoose做了计划,如:

 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在Mongo中改为ObjectId,因为我希望这可以帮助我更好地处理这些embedded的集合 – 它没有。

我想插入项目到指定的位置,或增加选定项目的计数,或删除选定的项目。

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); }) 

正如你所看到的,在项目上添加我使用线性search来find字段,在那里我可以推新制作的项目…这是非常非常丑陋的,我敢肯定,一定有很多简单的方法来做到这一点…

而且,增加或删除呢? 我不想以同样的方式…

而且,对于第四个问题:您如何看待ID? 如何实现它们? 我应该在任何地方使用ObjectIds,或者在任何地方都不需要?

任何帮助和想法表示赞赏!

我的愿景是使用embedded式文档,如果它们几乎是静态的。 你的对象看起来是dynamic的,所以我build议你尝试使用文档引用:

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

此外,我不build议调用您的模型“项目”。 用单数来调用它,比如“Item”。