mongoose.js:嵌入文档的_id

时间:2012-06-06 10:35:43

标签: node.js mongodb mongoose

我正在尝试使用mongoose和MongoDB将任务保存到任务列表中。我想将它冗余地保存在任务集合中,并作为嵌入文档保存在相应的列表文档中。

它运行正常但只有一点:列表的嵌入文档没有它们的objectIds。但是我需要它们以便在逻辑上将它们与tasks-collection中的文档连接起来。

我的架构:

var TaskSchema = new Schema({
    _id: ObjectId,
    title: String,
    list: ObjectId

});

var Task = mongoose.model('task', TaskSchema);

var ListSchema = new Schema({
    _id: ObjectId,
    title: String,
    tasks: [Task.schema]
});

var List = mongoose.model('list', ListSchema);

我的控制器/路由器:

app.post('/lists/:list_id/tasks', function(req, res) {

        var listId = req.params.list_id;   

        // 1. Save the new task into the tasks-collection.

        var newTask = new Task();
        newTask.title = req.body.title;
        newTask.list = listId; 

        console.log('TaskId:' + newTask._id);  // Returns undefined on the console!!!

        newTask.save(); // Works fine!

        // 2. Add the new task to the coresponding list.

        list.findById(listId, function(err, doc){

            doc.tasks.push(newTask);

            doc.save();  // Saves the new task in the list but WITHOUT its objectId

            });

        res.redirect('/lists/' + listId)

});

我能以不同的方式使用mongoose吗?或者我是否必须保存任务,然后在将其保存到列表中之前进行查询?

感谢您的建议: - )

2 个答案:

答案 0 :(得分:9)

我使用名为populate的强大功能解决了这个问题!

dtryon也是对的:你不需要在你的模型中声明你的_id ObjectIds,它们无论如何都会被添加。你必须嵌套这些东西,因为你的任务被异步保存,所以你必须确保在其他东西之前运行。

以下是解决方案:

架构:

var TaskSchema = new Schema({
    title: String,
    list: { type: Schema.ObjectId, ref: 'list' }

});

var Task = mongoose.model('task', TaskSchema);

var ListSchema = new Schema({
    title: String,
    tasks: [{ type: Schema.ObjectId, ref: 'task' }]
});

var List = mongoose.model('list', ListSchema);

控制器/路由器:

app.post('/lists/:list_id/tasks', function(req, res) {

    var listId = req.params.list_id;   

    var newTask = new Task();
    newTask.title = req.body.title;
    newTask.list = listId; 


    // WHEN SAVING, WRAP THE REST OF THE CODE

    newTask.save(function (err){
       if (err) {
            console.log('error saving new task');
            console.log(err);
        } else {
            console.log('new task saved successfully'); 

            list.findById(listId), function(err, doc){

                doc.tasks.push(newTask);

                doc.save(function (err){
                    if (err) {
                    console.log('error adding new task to list');
                    console.log(err);
                    } else {

                    console.log('new task saved successfully'); 
                    res.redirect('/lists/' + listId);

                    }  
                });
            });
        });
    });
});

现在它正确引用,并且使用填充功能,您可以非常舒适地访问条目。像魅力一样工作: - )

答案 1 :(得分:1)

我认为这可能与异步有关。您可能没有看到ObjectId,因为在推送list.findById之前,您可能正在调用newTask 。此外,在异步操作之外执行res.redirect也会遇到麻烦。

试试这个:

app.post('/lists/:list_id/tasks', function(req, res) {

        var listId = req.params.list_id;   

        // 1. Save the new task into the tasks-collection.

        var newTask = new Task();
        newTask.title = req.body.title;
        newTask.list = listId; 

        console.log('TaskId:' + newTask._id);  // Returns undefined on the console!!!

        // WHEN SAVING, WRAP THE REST OF THE CODE
        newTask.save(function (err){
            if (err) {
                console.log(err);
                    // do something
            }

            // 2. Add the new task to the coresponding list.

            list.findById(listId, function(err, doc){

                doc.tasks.push(newTask);

                doc.save();  // Saves the new task in the list but WITHOUT its objectId

                // REDIRECT AFTER SUCCESS
                res.redirect('/lists/' + listId)

            });
       });
});