使用findOneAndUpdate时如何检查文档是否被插入或更新?

问题描述 投票:0回答:6
Chatrooms.findOneAndUpdate({Roomname: room.Roomname},{ $setOnInsert: {status: true, userNum: 1}}, {new: true, upsert: true}, function(err, doc) {
    if(err) console.log(err);

    console.log("DOC " + doc)

    if(doc.status) {
        // FOUND ROOM SATTUS IS TRUE LOGIC 
        console.log(doc);
        // return callback(true)
    }
 });

上面的查询将返回给我更新或插入的实际文档,但我无法准确检查它是哪一个。如果我进行更新而不是 findOneandUpdate 我会返回此

{
    ok: 1,
    nModified: 0,
    n: 1,
    upserted: [ { index: 0, _id: 55df883dd5c3f7cda6f84c78 } ]
} 

如何返回文档和写入结果,或者至少返回写入结果中插入的字段。

node.js mongodb mongoose mongodb-query
6个回答
6
投票

自 2019 年 8 月 8 日起(Mongoose 版本 5.6.9),要设置的属性是“rawResult”而不是“passRawResult”:

M.findOneAndUpdate({}, obj, {new: true, upsert: true, rawResult:true}, function(err, d) {
    if(err) console.log(err);
    console.log(d);
});

输出:

{ lastErrorObject:
   { n: 1,
     updatedExisting: false,
     upserted: 5d4befa6b44b48c3f2d21c75 },
  value: { _id: 5d4befa6b44b48c3f2d21c75, rating: 4, review: 'QQQ' },
  ok: 1 }

还要注意,结果作为回调的第二个参数返回,而不是第三个参数。可以通过d.value检索文档。


4
投票

Mongoose 4.1.10 版本有一个名为

passRawResult
的选项,如果设置为
true
会导致传递
raw
参数。忽略此选项似乎默认为
false
并导致
raw
始终为
undefined
:

passRawResult:如果为 true,则传递来自 MongoDB 驱动程序的原始结果 作为第三个回调参数

http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate


4
投票

好吧,我的主要问题是我无法获取插入文档的_id,而无法检查它是否已更新/找到或插入。不过我了解到您可以生成自己的 ID。

id = mongoose.Types.ObjectId();    
Chatrooms.findOneAndUpdate({Roomname: room.Roomname},{ $setOnInsert: {_id: id, status: true, userNum: 1}}, {new: true, upsert: true}, function(err, doc) {
        if(err) console.log(err);

        if(doc === null) {

           // inserted document logic 
           // _id available for inserted document via id 
        } else if(doc.status) {

         // found document logic 
        }
     });

更新

猫鼬API v4.4.8

passRawResult:如果为 true,则将 MongoDB 驱动程序的原始结果作为第三个回调参数传递。


0
投票

我担心使用 FindOneAndUpdate 不能做你想做的事,因为它没有中间件和设置器,并且它在文档中提到了它:

虽然在使用 findAndModify 帮助器时将值转换为适当的类型,但不应用以下内容:

  • 默认值
  • 二传手
  • 验证者
  • 中间件

http://mongoosejs.com/docs/api.html在findOneAndUpdate中搜索它
如果您想获取更新前的文档和更新后的文档,您可以这样做:

Model.findOne({ name: 'borne' }, function (err, doc) {
if (doc){ 
  console.log(doc);//this is ur document before update
  doc.name = 'jason borne';
  doc.save(callback); // you can use your own callback to get the udpated doc
}
})

希望对你有帮助


0
投票

我不知道这是如何完全偏离轨道的,但对于所有

.XXupdate()
方法始终有“第三个”参数响应,这基本上是来自驱动程序的原始响应。这总是告诉您文档是否被“更新插入”:

Chatrooms.findOneAndUpdate(
   { "Roomname": room.Roomname },
   { "$setOnInsert": { 
      "status": true, "userNum": 1
   }},
   { "new": true, "upsert": true },
   function(err, doc,raw) {
    if(err) console.log(err);

    // Check if upserted
    if ( raw.lasErrorObject.n == 1 && !raw.lastErrorObject.updatedExisting ) {
        console.log("upserted: %s", raw.lastErrorObject.upserted);
    }

    console.log("DOC " + doc)

    if (doc.status) {
        // FOUND ROOM SATTUS IS TRUE LOGIC 
        console.log(doc);
        // return callback(true)
    }
});

这会告诉您刚刚更新插入的文档的

_id

来自“原始”响应中的类似内容:

{ lastErrorObject:
   { updatedExisting: false,
     n: 1,
     upserted: 55e12c65f6044f57c8e09a46 },
  value: { _id: 55e12c65f6044f57c8e09a46, 
           status: true,
           userNum: 1
           __v: 0 },
  ok: 1 }

完整的可复制列表:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

var testSchema = new Schema({
  name: String
});

var Test = mongoose.model('Test', testSchema, 'test');

async.series(
  [
    function(callback) {
      Test.remove({},callback);
    },
    function(callback) {
      async.eachSeries(
        ["first","second"],
        function(it,callback) {
          console.log(it);
          Test.findOneAndUpdate(
            { "name": "Bill" },
            { "$set": { "name": "Bill" } },
            { "new": true, "upsert": true },
            function(err,doc,raw) {
              console.log(raw),
              console.log(doc),
              callback(err);
            }
          );
        },
        callback
      );
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

哪个输出:

first
{ lastErrorObject:
   { updatedExisting: false,
     n: 1,
     upserted: 55e2a92328f7d03a06a2dd6b },
  value: { _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 },
  ok: 1 }
{ _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 }
second
{ lastErrorObject: { updatedExisting: true, n: 1 },
  value: { _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 },
  ok: 1 }
{ _id: 55e2a92328f7d03a06a2dd6b, name: 'Bill', __v: 0 }

0
投票

在 mongoose 8.1.3 中,要设置的属性是“includeResultMetadata”,而不是“rawResult”或“passRawResult”。

© www.soinside.com 2019 - 2024. All rights reserved.