Mongoose - 如果不存在则创建文档,否则,在任何一种情况下都更新 - 返回文档

Con*_*nor 50 javascript refactoring mongoose node.js

我正在寻找一种方法来重构我的部分代码,使其更短更简单,但我不太了解Mongoose,我不知道如何继续.

我正在尝试检查一个集合是否存在文档,如果它不存在,则创建它.如果确实存在,我需要更新它.在任何一种情况下,我都需要访问文档的内容.

到目前为止我设法做的是查询特定文档的集合,如果找不到,则创建一个新文档.如果找到它,我会更新它(当前使用日期作为虚拟数据).从那里我可以访问我的初始find操作中找到的文档或新保存的文档,这可行,但必须有一个更好的方法来完成我所追求的.

这是我的工作代码,没有分散注意力.

var query = Model.find({
    /* query */
}).lean().limit(1);

// Find the document
query.exec(function(error, result) {
    if (error) { throw error; }
    // If the document doesn't exist
    if (!result.length) {
        // Create a new one
        var model = new Model(); //use the defaults in the schema
        model.save(function(error) {
            if (error) { throw error; }
            // do something with the document here
        });
    }
    // If the document does exist
    else {
        // Update it
        var query = { /* query */ },
            update = {},
            options = {};

        Model.update(query, update, options, function(error) {
            if (error) { throw error; }
            // do the same something with the document here
            // in this case, using result[0] from the topmost query
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

我已经研究了findOneAndUpdate其他相关方法,但我不确定它们是否适合我的用例,或者我是否理解如何正确使用它们.谁能指出我正确的方向?

(可能)相关问题:


编辑

在我的搜索中,我没有遇到向我指出的问题,但在回顾了那里的答案后,我想出了这个.在我看来,这当然更漂亮,并且它有效,所以除非我做了一些可怕的错误,否则我认为我的问题可能会被关闭.

我很感激我的解决方案的任何其他输入.

// Setup stuff
var query = { /* query */ },
    update = { expire: new Date() },
    options = { upsert: true };

// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
    if (!error) {
        // If the document doesn't exist
        if (!result) {
            // Create it
            result = new Model();
        }
        // Save the document
        result.save(function(error) {
            if (!error) {
                // Do something with the document
            } else {
                throw error;
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

小智 92

您正在寻找new选项参数.该new选项返回新创建的文档(如果创建了新文档).像这样使用它:

var query = {},
    update = { expire: new Date() },
    options = { upsert: true, new: true, setDefaultsOnInsert: true };

// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
    if (error) return;

    // do something with the document
});
Run Code Online (Sandbox Code Playgroud)

由于upsert如果未找到文档而创建文档,则无需手动创建另一个文档.

  • 除未使用在我的架构中定义的默认值填充新创建的文档外,这似乎可行。很混乱。您知道有什么原因吗? (2认同)
  • @Connor是的,它是mongoose的默认功能,虽然有一个选项可以解决这个问题.检查我更新的答案. (2认同)

Jos*_*ush 6

由于您希望将代码的一部分重构得更短,更简单,

  1. 使用 async / await
  2. .findOneAndUpdate()按照此答案的建议使用

let query = { /* query */ };
let update = {expire: new Date()};
let options = {upsert: true, new: true, setDefaultsOnInsert: true};
let model = await Model.findOneAndUpdate(query, update, options);
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记用 try&catch 来结束它:) (2认同)

归档时间:

查看次数:

54353 次

最近记录:

6 年,5 月 前