(mongoose/承诺)如何检查文档是否使用findOneAndUpdate和upsert创build

考虑这个代码,我需要创build或更新一个特定的文档。

Inbox.model.findOneAndUpdate({ number: req.phone.number }, { number: req.phone.number, country: req.phone.country, token: hat(), appInstalled: true }, { new: true, upsert: true }).then(function(inbox){ /* do something here with inbox, but only if the inbox was created (not updated) */ }); 

mongoose是否有设施可以区分文件是否被创build或更新? 我需要new: true因为我需要调用inbox函数。

对于mongoose的.findOneAndUpdate()或任何.findAndModify()核心驱动程序变体,实际的callback签名具有“三个”参数:

  function(err,result,raw) 

首先是任何错误响应,然后修改或原始文档取决于选项,第三个是发出的语句的写入结果。

第三个参数应该像这样返回数据:

 { lastErrorObject: { updatedExisting: false, n: 1, upserted: 55e12c65f6044f57c8e09a46 }, value: { _id: 55e12c65f6044f57c8e09a46, number: 55555555, country: 'US', token: "XXX", appInstalled: true, __v: 0 }, ok: 1 } 

如果lastErrorObject.updatedExisting的一致字段是true/false取决于upsert是否发生。 请注意,当此属性为false时,还有一个“upserted”值包含新文档的_id响应,但不是true

因此,您可以修改您的处理以考虑第三个条件,但这只适用于callback而不是承诺:

 Inbox.model.findOneAndUpdate( { "number": req.phone.number }, { "$set": { "country": req.phone.country, "token": hat(), "appInstalled": true } }, { "new": true, "upsert": true }, function(err,doc,raw) { if ( !raw.lastErrorObject.updatedExitsing ) { // do things with the new document created } } ); 

在那里我也强烈build议你在这里使用更新操作符而不是原始对象,因为原始对象将总是覆盖整个文档,但像$set这样的操作符只会影响列出的字段。

还要注意的是,对于语句的任何匹配“查询参数”都会自动分配到新文档中,只要它们的值是未find的精确匹配即可。

鉴于使用承诺似乎没有返回额外的信息出于某种原因,那么不要看到如何设置{ new: false}以外的承诺,基本上没有文档返回时,这是一个新的。

你有所有的文件数据,无论如何,所以它不是你真的需要的数据返回无论如何。 事实上,本地驱动程序方法是如何处理核心内容的,只有在发生upsert时才会响应“upserted” _id值。

这真的归结为在这个网站上讨论的另一个问题,在下面:

可以承诺有多个参数onFulfilled?

如果这真的归结为承诺答复中的多个对象的解决,这在本地指导中不直接支持,但是在那里列出了一些方法。

所以,如果你实现了蓝鸟承诺,并使用.spread()方法,那么一切都很好:

 var async = require('async'), Promise = require('bluebird'), mongoose = require('mongoose'), Schema = mongoose.Schema; mongoose.connect('mongodb://localhost/test'); var testSchema = new Schema({ name: String }); var Test = mongoose.model('Test',testSchema,'test'); Promise.promisifyAll(Test); Promise.promisifyAll(Test.prototype); async.series( [ function(callback) { Test.remove({},callback); }, function(callback) { var promise = Test.findOneAndUpdateAsync( { "name": "Bill" }, { "$set": { "name": "Bill" } }, { "new": true, "upsert": true } ); promise.spread(function(doc,raw) { console.log(doc); console.log(raw); if ( !raw.lastErrorObject.updatedExisting ) { console.log( "new document" ); } callback(); }); } ], function(err) { if (err) throw err; mongoose.disconnect(); } ); 

哪一个当然会返回这两个对象,然后可以一致地访问:

 { _id: 55e14b7af6044f57c8e09a4e, name: 'Bill', __v: 0 } { lastErrorObject: { updatedExisting: false, n: 1, upserted: 55e14b7af6044f57c8e09a4e }, value: { _id: 55e14b7af6044f57c8e09a4e, name: 'Bill', __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) { Test.findOneAndUpdate( { "name": "Bill" }, { "$set": { "name": "Bill" } }, { "new": true, "upsert": true } ).then(function(doc,raw) { console.log(doc); console.log(raw); if ( !raw.lastErrorObject.updatedExisting ) { console.log( "new document" ); } callback(); }); } ], function(err) { if (err) throw err; mongoose.disconnect(); } ); 

为了logging,本机驱动程序本身没有这个问题,因为响应对象实际上只是对象返回的任何错误:

 var async = require('async'), mongodb = require('mongodb'), MongoClient = mongodb.MongoClient; MongoClient.connect('mongodb://localhost/test',function(err,db) { var collection = db.collection('test'); collection.findOneAndUpdate( { "name": "Bill" }, { "$set": { "name": "Bill" } }, { "upsert": true, "returnOriginal": false } ).then(function(response) { console.log(response); }); }); 

所以总是这样的:

 { lastErrorObject: { updatedExisting: false, n: 1, upserted: 55e13bcbf6044f57c8e09a4b }, value: { _id: 55e13bcbf6044f57c8e09a4b, name: 'Bill' }, ok: 1 }