使用 Mongoose 返回更新的集合

Posted

技术标签:

【中文标题】使用 Mongoose 返回更新的集合【英文标题】:Return updated collection with 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 的未更新对象) 【参考方案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 的支持。

以上是关于使用 Mongoose 返回更新的集合的主要内容,如果未能解决你的问题,请参考以下文章

使用 mongoose 访问现有的 mongodb 集合

Mongoose更新嵌套数组

无法得到我在 nodejs / mongoose / bluebird 中返回的承诺

MongoDB VS MySQL - 为啥 mongo/mongoose 会自动创建数据库和集合?

NodeJS Express Mongoose 返回空 []

mongoose基本增删改查