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

时间:2015-09-10 13:45:58

标签: node.js mongodb mongoose

我需要提一下,我完全清楚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​​来操作这些数据。我知道,如果我创建一个新的部门,我应该添加对公司的引用,我应该在这个公司的部门数组中创建它的引用。简单。但是如果用户更改了部门的公司财产呢?比如说,人力资源部门曾经属于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;
};

对于这种情况有没有优雅的解决方案,或者它应该是它应该是什么?

1 个答案:

答案 0 :(得分:0)

我看到你还没有捕捉到node.js异步性质的本质...例如你在department.save之前有一个评论说:最后......好了早期的逻辑可能会非常那个时候还在执行...我还强烈建议你避免使用回调方法来学习如何使用promises