【问题标题】:How can I create/find in Mongoose?如何在 Mongoose 中创建/查找?
【发布时间】:2014-09-26 20:09:39
【问题描述】:

有时我需要一个文档存在于数据库中,我很乐意使用现有文档,或者在缺少文档时创建文档,然后使用新文档。

这似乎是一个相当常见的用例,但我查看了 Mongoose docs 并找不到任何东西。

findOneAndUpdate()update()upsert: true 这样的Mongoose Collection 方法是关于修改文档的——如果文档存在,我不想修改它,只是获取它的引用。

示例:(为@neillunn 添加)我想添加一个引用“名称”为“foo”的公司的用户。在此之前,我想用{name: 'foo'} 查找一家公司,如果它不存在就创建它。

示例 2:(为@neillunn 添加)我现在用来处理示例场景的代码:

// Find or create an an instance and return a cb with a reference to it.
var findOrCreate = function(model, criteria, cb){
    model.update(criteria, criteria, {upsert: true}, function(err, numberAffected, raw){
        if ( ! raw.updatedExisting ) {
            console.log('Created instance')
        } else {
            console.log('Found existing instance')
        }           
        model.findOne(criteria, cb)
    })
}

注意findOneAndUpdate() 不起作用,因为它会尝试修改现有文档,并获得“重复键错误索引”

【问题讨论】:

  • 不太清楚。您正在寻找正确的东西,但是为什么您只想本质上“查找”它是否存在,而如果不存在则“修改/更新”?差异似乎不言自明。也许更好地解释您的用例。
  • 所以你基本上想要实现自动关系?由于猫鼬没有正式或以编程方式支持关系,我认为您需要执行 2 个查询来实现这一点。
  • @Charminbear 不是关系,只是根据需要查找或制作。如果我的示例我找到/创建了一个公司实例,因为我需要引用 company._id,但这只是当前的用例。
  • @mikemaccana: github.com/drudge/mongoose-findorcreate您正在寻找类似的东西?
  • 这个问题非常有用的解决方案:stackoverflow.com/a/7592756/4025963

标签: javascript node.js mongodb mongoose


【解决方案1】:

正如 cmets 中所述,有一个 mongoose 插件可以做到这一点: http://github.com/drudge/mongoose-findorcreate

This Thread 还描述了一种无需插件即可实现此目的的方法。我只是不确定它是否适用于猫鼬。

【讨论】:

    【解决方案2】:

    这里非常有用的解决方案:https://stackoverflow.com/a/7592756/4025963:

    var Counters = new Schema({
      _id: String,
      next: Number     
    });
    
    Counters.statics.findAndModify = function (query, sort, doc, options, callback) {
      return this.collection.findAndModify(query, sort, doc, options, callback);
    };
    
    var Counter = mongoose.model('counters', Counters);
    
    Counter.findAndModify({ _id: 'messagetransaction' }, [], { $inc: { next: 1 } }, {}, function (err, counter) {
      if (err) throw err;
      console.log('updated, counter is ' + counter.next);
    });
    

    习惯了 Promise 会更有趣:

    Counters.statics.findAndModify =
        function findAndModify(query, sort, update, options, callback) {
            const promised = q.nbind(this.collection.findAndModify, this.collection);
            return promised(query || {}, sort || [], update || {}, options, callback);
        };
    

    【讨论】:

      【解决方案3】:

      Mongoose has an inbuilt findOneAndUpdate function 可以找到,如果数据不存在,它将创建数据。基本上下面是它是如何完成的:

      var modelDoc = new MyModel({ foo: 'bar' });
      
      MyModel.findOneAndUpdate(
          {foo: 'bar'}, // find a document with that filter
          modelDoc, // document to insert when nothing was found
          {upsert: true, new: true, runValidators: true}, // options
          function (err, doc) { // callback
              if (err) {
                  // handle error
              } else {
                  // handle document
              }
          }
      );
      

      options 参数对于插入工作至关重要。`

      通过设置upsert: true,如果{foo: 'bar'}filter 没有找到结果,您可以命令MongoDB 将modelDoc 文档实际添加到集合中。

      new: true 选项更改回调函数中返回的内容。如果为 false,则 doc 将在更新之前包含文档(或在插入之前为 null)。如果为真,则 doc 包含更新或创建后的文档。虽然 false 是默认选项,但我想大多数人实际上更喜欢它是 true。

      如果您希望 Mongoose 运行验证器,则必须设置 runValidators: true 选项。默认情况下,使用findOneAndUpdate()时不会执行这些。

      【讨论】:

      • 来自文档:“当使用带有 findOneAndUpdate() 方法的 upsert: true 选项,并且不在查询字段上使用唯一索引时,多个实例具有相似查询字段的 findOneAndUpdate() 操作可能导致在某些情况下插入重复文档。"
      猜你喜欢
      • 2017-02-27
      • 1970-01-01
      • 2017-03-07
      • 2020-04-12
      • 2017-07-21
      • 1970-01-01
      • 2015-01-16
      • 2016-05-20
      • 1970-01-01
      相关资源
      最近更新 更多