繁体   English   中英

使用Mongoose和Node.js在MongoDB中删除一对多和多对多关系中的引用

[英]Removing references in one-to-many and many-to-many relationships in MongoDB using Mongoose and Node.js

我需要提到的是,我完全意识到MongoDB并不是关系数据库。 但是,它支持引用其他文档,因此支持某些功能imo。 无论如何,我有这种关系:一个公司has many部门,一个部门belongs to一个公司。

company.js

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var CompanySchema = new Schema({
    name: {
        type: String,
        unique: true,
        required: true
    },
    departments: [{
        type: Schema.Types.ObjectId,
        ref: 'Department'
    }],
    dateCreated: {
        type: Date,
        default: Date.now
    },
    dateUpdated: {
        type: Date,
        default: Date.now
    }
});

module.exports = mongoose.model('Company', CompanySchema);

department.js

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var DepartmentSchema = new Schema({
    name: {
        type: String,
        required: true
    },
    company: {
        type: Schema.Types.ObjectId,
        ref: 'Company'
    },
    dateCreated: {
        type: Date,
        default: Date.now
    },
    dateUpdated: {
        type: Date,
        default: Date.now
    }
});

module.exports = mongoose.model('Department', DepartmentSchema);

现在,我正在编写Node.js逻辑以使用API​​来处理此数据。 我知道如果创建一个新部门,则应添加对Company的引用,并应在此Company的Departments数组中创建其引用。 简单。 但是,如果用户更改部门的Company属性怎么办? 假设人力资源部门曾经属于公司A,但是现在有用户将其移至公司B? 我们需要从公司A的数组中删除对该部门的引用,并将其推到公司B。这与我们要删除部门的情况相同。 我们需要找到它所属的公司并取消其关联。 我的解决方案是在ATM上运行,但看起来很笨拙。

routes.js

var Department = require('../../models/department'),
    Company = require('../../models/company');

module.exports = function(express) {
    var router = express.Router();

    router.route('/')
        .get(function(req, res) {
            // ...
        })
        .post(function(req, res) {
            // ...
        });

    router.route('/:id')
        .get(function(req, res) {
            // ...
        })
        .put(function(req, res) {

            // First we need to find the department with the request parameter id
            Department.findOne({ _id: req.params.id }, function(err, data) {
                if (err) return res.send(err);
                var department = data;
                // department.name = req.body.name || department.name; Not relevant

                // If the company to which the department belongs is changed
                if (department.company != req.body.company._id) {

                    // We should find the previous company
                    Company.findOne({ _id: department.company }, function(err, data) {
                        if (err) return res.send(err);
                        var company = data;

                        // Loop through its departments
                        for (var i = 0; i < company.departments.length; i++) {
                            if (company.departments[i].equals(department._id)) {

                                // And splice this array to remove the outdated reference
                                company.departments.splice(i, 1);
                                break;
                            }
                        }
                        company.save(function(err) {
                            if (err) return res.send(err);
                        });
                    });

                    // Now we find this new company which now holds the department in question
                    // and add our department as a reference
                    Company.findOne({ _id: req.body.company._id }, function(err, data) {
                        if (err) return res.send(err);
                        var company = data;
                        company.departments.push(department._id);
                        company.save(function(err) {
                            if (err) return res.send(err);
                        });
                    });
                }

                // department.company = req.body.company._id || department.company; Not relevant
                // department.dateUpdated = undefined; Not relevant

                // And finally save the department
                department.save(function(err) {
                    if (err) return res.send(err);
                    return res.json({ success: true, message: 'Department updated successfully.' });
                });
            });
        })
        .delete(function(req, res) {

            // Since we only have id of the department being deleted, we need to find it first
            Department.findOne({ _id: req.params.id}, function(err, data) {
                if (err) return res.send(err);
                var department = data;

                // Now we know the company it belongs to and should dis-associate them
                // by removing the company's reference to this department
                Company.findOne({ _id: department.company }, function(err, data) {
                    if (err) return res.send(err);
                    var company = data;

                    // Again we loop through the company's departments array to remove the ref
                    for (var i = 0; i < company.departments.length; i++) {
                        if (company.departments[i].equals(department._id)) {
                            company.departments.splice(i, 1);
                            break;
                        }
                    }
                    company.save(function(err) {
                        if (err) return res.send(err);
                    });

                    // I guess it should be synchronously AFTER everything is done,
                    // since if it is done in parallel with Department.findOne(..)
                    // piece, the remove part can happen BEFORE the dep is found
                    Department.remove({ _id: req.params.id }, function(err, data) {
                        if (err) return res.send(err);
                        return res.json({ success: true, message: 'Department deleted successfully.' });
                    });
                });
            });
        });

    return router;
};

对于这种情况,是否有任何优雅的解决方案?

我看到您尚未掌握node.js异步本质的本质...例如,您在department.save之前有一条注释,其中说:最后……很好,早期的逻辑可能仍会在那时候...我也强烈建议您避免使用回调方法,并学习如何使用Promise做到这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM