【问题标题】:Mongoose - Create document if not exists, otherwise, update- return document in either caseMongoose - 如果不存在则创建文档,否则,更新 - 在任何一种情况下都返回文档
【发布时间】:2016-01-23 04:24:45
【问题描述】:

我正在寻找一种方法来重构我的部分代码,使其更短更简单,但我不太了解 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
        });
    }
});

我研究了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;
            }
        });
    }
});

【问题讨论】:

  • 阙:Mongoose.js:如何实现创建或更新?答:stackoverflow.com/questions/7267102/…
  • 老实说,我现在觉得自己很愚蠢。我在搜索时没有找到那个问题,但回想起来,答案似乎很容易掌握。感谢您的帮助!

标签: javascript node.js mongoose refactoring


【解决方案1】:

您正在寻找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
});

由于upsert如果没有找到文档就会创建一个文档,所以你不需要手动创建另一个。

【讨论】:

  • 这似乎工作,除了新创建的文档没有填充我的架构中定义的默认值。很混乱。有什么原因,你知道吗?
  • @Connor 是的,它是猫鼬的默认功能,尽管有一个选项可以解决这个问题。检查我更新的答案。
  • 有点奇怪的小怪癖,但我认为开发人员有他们的理由。这是解决我的问题的一个非常棒的解决方案,所以感谢您的帮助!
  • 在这种情况下,您如何识别发送的状态码? 200=更新。 201 创建
  • 如果我要更新的对象有一个 id 列表并且我想在其中添加一个新的 id 怎么办?这会替换还是添加到列表中?
【解决方案2】:

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

  1. 使用async / await
  2. 按照answer 中的建议使用.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);

【讨论】:

  • 如果您使用 api 获取 json 中的项目并希望使用模型执行以下操作:let update = JSON.parse(data);
  • 别忘了用 try&catch 结束它 :)
【解决方案3】:
///This is simple example explaining findByIDAndUpdate from my code added with try catch block to catch errors
try{
const options = {
            upsert: true,
            new: true,
            setDefaultsOnInsert: true
        };
        const query = {
            $set: {
                description: req.body.description,
                title: req.body.title
            }
        };
        const survey = await Survey.findByIdAndUpdate(
            req.params.id,
            query,
            options
        ).populate("questions");
}catch(e){
console.log(e)
}

【讨论】:

    【解决方案4】:

    这是一个例子:

    const mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/rsvp', {useNewUrlParser: true, useUnifiedTopology: true});
    
    const db = mongoose.connection;
    
    db.on('error', () => {
      console.log('mongoose connection error');
    });
    
    db.once('open', () => {
      console.log('mongoose connected successfully');
    });
    
    const rsvpSchema = mongoose.Schema({
      firstName: String,
      lastName: String,
      email: String,
      guests: Number
    });
    
    const Rsvp = mongoose.model('Rsvp', rsvpSchema);
    
    
    // This is the part you will need... In this example, if first and last name match, update email and guest number. Otherwise, create a new document. The key is to learn to put "upsert" as the "options" for the argument.
    const findRsvpAndUpdate = (result, callback) => {
    
      Rsvp.findOneAndUpdate({firstName: result.firstName, lastName: result.lastName}, result, { upsert: true }, (err, results) => {
        if (err) {
          callback(err);
        } else {
          callback(null, results);
        }
      })
    };
    
    
    // From your server index.js file, call this...
    app.post('/rsvps', (req, res) => {
      findRsvpAndUpdate(req.body, (error, result) => {
        if (error) {
          res.status(500).send(error);
        } else {
          res.status(200).send(result);
        }
      })
    });

    【讨论】:

      【解决方案5】:

      这是我正在使用的示例。我必须为 UI 更新等返回自定义响应。这可以更短。用户是

      const UserScheme = mongoose.Schema({
          _id: String,
          name: String,
          city: String,
          address: String,
      },{timestamps: true});
      
      const User = mongoose.model('Users', UserScheme);
      
      
      async function userUpdateAdd(data){
          var resp = '{"status": "error"}';
          if(data){
          var resp = await User.updateOne({ _id: data._id }, data).then(function(err, res){
              console.log("database.userUpdateAdd -> Update data saved in database!");
              if(err){
                  var errMessage = err.matchedCount == 0 ? "User Record does not exist, will create new..." : "Record not updated";
                  // If no match, create new
                  if(err.matchedCount == 0){
                      const create_user = new User(data);
                      resp = create_user.save().then(function(){
                          console.log("database.userUpdateAdd -> Data saved to database!");
                          return '{"status":"success", "message": "New User added successfully"}';
                      });
                      return resp;
                  }
      
                  // Exists, return success update message
                  if(err.matchedCount == 1){
                      return '{"status": "success", "message" : "Update saved successfully"}';
                  } else {
                      return '{"status": "error", "code": "' + err.modifiedCount + '", "message": "' + errMessage + '"}';
                  }
              }
              })
              .catch((error) => {
                  //When there are errors We handle them here
                  console.log("database.userUpdateAdd -> Error, data not saved! Server error");
                  return '{"status": "error", "code": "400", "message": "Server error!"}';
              });
          }
          return resp;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-09-13
        • 2021-09-12
        • 2019-08-04
        • 2016-08-01
        • 2021-02-24
        • 1970-01-01
        • 2020-05-11
        • 1970-01-01
        • 2021-03-21
        相关资源
        最近更新 更多