考虑这段代码,我需要创建或更新特定文档。
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是否有能力区分文件是否已创建或更新?我需要new: true
,因为我需要调用inbox
上的函数。
答案 0 :(得分:4)
对于mongoose的.findOneAndUpdate()
或任何.findAndModify()
核心驱动程序变体,实际的回调签名有三个"三个"参数:
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
,则_id
中的一致字段取决于是否发生upsert的结果。请注意,还有一个" upserted"当此属性为false
时,包含新文档的true
响应的值,而不是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
}
}
);
时的值。
因此,您将修改您的处理以考虑第三个条件,但这仅适用于回调而不是承诺:
{ new: false}
我强烈建议你在这里使用update operators而不是原始对象,因为原始对象将始终覆盖整个文档,但像$set
这样的运算符只会影响列出的字段。
还注意到任何匹配的"查询参数"只要它们的值与未找到的完全匹配,就会在新文档中自动分配该语句。
鉴于使用promise似乎由于某种原因似乎没有返回附加信息,那么除了设置_id
之外的其他承诺并没有看到这是可能的,并且基本上没有返回任何文档然后它&#39一个新的。
无论如何,您都希望插入所有文档数据,因此您不一定非常需要返回的数据。实际上,本机驱动程序方法在核心处理这个问题,并且只响应" upserted"发生upsert时的.spread()
值。
这真的归结为本网站讨论的另一个问题,在:
Can promises have multiple arguments to onFulfilled?
这实际上归结为承诺响应中多个对象的解析,这是本地特征中没有直接支持的东西,但是那里列出了一些方法。
因此,如果您实施Bluebird承诺并在那里使用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();
}
);
以下是展示正常行为的完整列表:
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 }
所以总是这样:
class CompareRectangles(object):
debugging = True
def globals():
global debugging
debugging = True
def __init__(self,r1,r2):
# globals()
self.r1 = r1
self.r2 = r2
self.initialise_boundary_tests()
def method(self):
if debugging:
print("hello debugger")
答案 1 :(得分:0)
对于将其用于Promises的人们,根据this link from Mongoosejs.com,我们可以将rawQuery: true
与其他选项一起使用。
const filter = { name: 'Will Riker' };
const update = { age: 29 };
await Character.countDocuments(filter); // 0
let res = await Character.findOneAndUpdate(filter, update, {
new: true,
upsert: true,
rawResult: true // Return the raw result from the MongoDB driver
});
res.value instanceof Character; // true
// The below property will be `false` if MongoDB upserted a new
// document, and `true` if MongoDB updated an existing object.
res.lastErrorObject.updatedExisting; /
,此查询的结果将采用
格式{ lastErrorObject:
{ n: 1,
updatedExisting: false,
upserted: 5e6a9e5ec6e44398ae2ac16a },
value:
{ _id: 5e6a9e5ec6e44398ae2ac16a,
name: 'Will Riker',
__v: 0,
age: 29 },
ok: 1 }
因此可以在data.value
上访问文档