【问题标题】:Return updated collection with Mongoose使用 Mongoose 返回更新的集合
【发布时间】:2014-01-07 04:44:37
【问题描述】:

我使用 nodejs/express/mongoose/angularjs。我想更新一个名为 Lists 的集合,它有几个属性,其中一个是项目数组。在下面的代码中,我在 items 数组中推送了一个新的任务项。一切正常,但是更新功能不会发回更新的集合,然后我必须对数据库执行另一个查询。有没有更有效的方法来做到这一点?

nodejs/express 代码:

exports.addTaskToList = function(req, res) {
    var listId = req.params.Id;
    var taskId = req.params.TaskId;
    Lists.update({_id: listId}, {$push: {items: taskId}}, {safe:true, upsert: true}, function(err, result){
        if(err) {
            console.log('Error updating todo list. ' + err);
        }
        else{
            console.log(result + ' todo list entry updated - New task added');
            Lists.findById(listId).populate('items').exec(function (err, updatedEntry) {
                if (err) {
                    console.log('Unable to retrieve todo list entry.');
                }
                res.send(JSON.stringify(updatedEntry));
            });
        }           
    });
};

此外,数组 items 是一个 ObjectId 数组。这些项目位于单独的架构中,因此位于单独的集合中。是否可以推送整个对象而不仅仅是它的 _id,这样就不会创建另一个集合?

【问题讨论】:

  • 考虑将findOneAndUpdate{ new: true } 选项一起使用。它将执行更新并返回更新的对象。 (或将new 设置为false 的未更新对象)

标签: javascript node.js mongodb express mongoose


【解决方案1】:

update method不返回更新的文档:

但是,如果我们不需要应用程序中返回的文档,并且 只想直接更新数据库中的属性, Model#update 适合我们。

如果您需要更新并返回文档,请考虑以下选项之一:

传统方法:

Lists.findById(listId, function(err, list) {
    if (err) {
        ...
    } else {
        list.items.push(taskId)
        list.save(function(err, list) {
            ...
        });
    }
});

更短的方法:

Lists.findByIdAndUpdate(listId, {$push: {items: taskId}}, function(err, list) {
    ...
});

【讨论】:

  • 是的,但需要注意的是,findByIdAndUpdate 不会运行 prepost 和其他模式方法,因此 mySchema.pre('save') 无法使用它。
  • 此外,它不会返回“新”的更新元素,而是“旧”元素。如果您想要实际更新的元素,则必须添加选项 {new : true}
  • 上面的评论回答了我在这里寻找的问题。
【解决方案2】:

关于你的最后一个问题:

是否可以推送整个对象而不仅仅是它的 _id 以便 没有创建另一个集合?

答案是肯定的。您可以使用 Mongoose (documentation on sub-documents here) 在文档中轻松存储子文档。通过稍微更改架构,您可以将整个项目对象(不仅仅是项目_id)推送到列表架构中定义的项目数组中。但是你需要修改你的架构,例如:

var itemSchema = new Schema({ 
    // Your Item schema goes here
    task: 'string'       // For example
});

var listSchema = new Schema({
    // Your list schema goes here
    listName: String,    // For example...
    items: [itemSchema]  // Finally include an array of items
});

通过将item 对象添加到列表的items 属性,然后保存该列表 - 您的新项目将被持久保存到列表集合中。例如,

var list = new List({
    listName: "Things to do"
});

list.items.push({
    task: "Mow the lawn"
});

list.save(function(error, result) {
    if (error) // Handle error
    console.log(result.list) // Will contain your item instance
});

因此,当您加载列表时,items 属性将预先填充您的项目数组。

这是因为 Items 将不再将其保存为单独的集合。它将作为 List 的子文档保存到 List 集合中。

【讨论】:

  • 谢谢布兰查德先生(说法语??)。我已经看到了这个,但我想知道如何有效地检索一个项目。我这样做的方式非常方便,因为有一个生成的_id,我不想自己打扰它。我需要更多地探索这条途径,谢谢。
  • 该文档回答了我的问题:“每个文档都有一个 _id。DocumentArrays 有一个特殊的 id 方法可以通过它的 _id 查找文档。”
【解决方案3】:

使用 findOneAndUpdate() 方法并在查询参数中使用选项作为 { "new": true}

return this.sessionModel
       .findOneAndUpdate({user_id: data.user_id}, {$set:{session_id: suuid}}, { "new": true})
       .exec()
       .then(data=>{
        return {
          sid: data.session_id
            }
        })

【讨论】:

  • 感谢@Vladimir Marton 的支持。
猜你喜欢
  • 1970-01-01
  • 2012-08-30
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 2018-06-09
  • 1970-01-01
  • 2021-10-25
  • 2020-07-22
相关资源
最近更新 更多