【问题标题】:Inserting, updating and removing from a complex embedded collection in MongoDB from Node using Mongoose使用 Mongoose 从 Node 中插入、更新和删除复杂的 MongoDB 嵌入式集合
【发布时间】:2013-12-04 10:49:21
【问题描述】:

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

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

示例数据收集如下所示:

[
{"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,因为我希望这将有助于我更好地处理这些嵌入的集合 - 它没有。

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

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?如何实施它们?我应该在任何地方都使用 ObjectId,还是在任何地方都不需要?

感谢任何帮助和想法!

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    我的愿景是,如果嵌入式文档几乎是静态的,您可以使用它们。您的对象在我看来是动态的,因此我建议您尝试改用文档引用:

    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”。

    【讨论】:

    • 对不起,回答迟了:重新考虑和实施这个解决方案花了一些时间,但它工作得很好,非常感谢:放弃嵌入式文档的想法本来是最后一个,但是代码现在很多简单了。
    • 没问题,但也请注意,嵌入式文档的检索速度比与参考相关的文档快得多。因此,有时您可能希望使用它们,例如,为用户保留不同的联系方式(电子邮件、推特、脸书、实际地址等)
    猜你喜欢
    • 2013-03-29
    • 2016-03-15
    • 2021-08-14
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2020-07-25
    • 2012-11-04
    相关资源
    最近更新 更多