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

时间:2015-10-23 15:05:17

标签: javascript node.js mongoose refactoring

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

4 个答案:

答案 0 :(得分:76)

您正在寻找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创建了文档但未找到文档,因此您无需手动创建另一个文档。

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:0)

@Service class MyService {
    JpaRepository<B> repository;
    public void accept(List<B> items) {
        List<B> summed = 
            items.stream().collect(groupingBy(B::getName, summarizingDouble(B::getWeight)))
             .entrySet().stream().map(e -> new B(e.getKey(), e.getValue()))
             .collect(toList());
        repository.save(summed);
    }
}

答案 3 :(得分:-1)

这是一个例子:

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);
    }
  })
});