Mat*_*Way 5 mongoose mongodb node.js promise mongodb-query
考虑这段代码,我需要创建或更新特定文档.
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)
*/
});
Run Code Online (Sandbox Code Playgroud)
mongoose是否有能力区分是否创建或更新了文档?我需要new: true
因为我需要调用函数inbox
.
在的情况下.findOneAndUpdate()
,或任何一种.findAndModify()
核心的猫鼬驱动程序变种,实际回调签名具有“三防”参数:
function(err,result,raw)
Run Code Online (Sandbox Code Playgroud)
第一个是任何错误响应,然后是根据选项的修改或原始文档,第三个是已发布语句的写入结果。
第三个参数应该像这样返回数据:
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e12c65f6044f57c8e09a46 },
value: { _id: 55e12c65f6044f57c8e09a46,
number: 55555555,
country: 'US',
token: "XXX",
appInstalled: true,
__v: 0 },
ok: 1 }
Run Code Online (Sandbox Code Playgroud)
根据是否发生 upsert 的结果,lastErrorObject.updatedExisting
其中的一致字段为两者true/false
之一。请注意,_id
当此属性为 时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
}
}
);
Run Code Online (Sandbox Code Playgroud)
我还强烈建议您在这里使用更新运算符而不是原始对象,因为原始对象将始终覆盖整个文档,而运算符之类的$set
只会影响列出的字段。
还要注意,只要它们的值是未找到的精确匹配,语句的任何匹配“查询参数”都会自动分配到新文档中。
鉴于出于某种原因,使用承诺似乎不会返回附加信息,那么除了设置之外,看不到承诺是如何实现的,{ new: false}
并且基本上当没有返回文档时,它就是一个新文档。
无论如何,您都拥有预期要插入的所有文档数据,因此您实际上并不需要返回该数据。实际上,本机驱动程序方法是如何在核心处理此问题的,并且仅_id
在发生 upsert 时才以“upsert ”值进行响应。
这实际上归结为本网站上讨论的另一个问题,位于:
这实际上归结为承诺响应中多个对象的解析,这在本机规范中不直接支持,但那里列出了一些方法。
因此,如果您实现 Bluebird 承诺并在.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();
}
);
Run Code Online (Sandbox Code Playgroud)
这当然会返回两个对象,然后您可以一致地访问:
{ _id: 55e14b7af6044f57c8e09a4e, name: 'Bill', __v: 0 }
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e14b7af6044f57c8e09a4e },
value: { _id: 55e14b7af6044f57c8e09a4e, name: 'Bill', __v: 0 },
ok: 1 }
Run Code Online (Sandbox Code Playgroud)
这是一个完整的清单,展示了正常行为:
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();
}
);
Run Code Online (Sandbox Code Playgroud)
作为记录,本机驱动程序本身没有这个问题,因为响应对象实际上只是除了任何错误之外返回的对象:
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);
});
});
Run Code Online (Sandbox Code Playgroud)
所以它总是这样的:
{ lastErrorObject:
{ updatedExisting: false,
n: 1,
upserted: 55e13bcbf6044f57c8e09a4b },
value: { _id: 55e13bcbf6044f57c8e09a4b, name: 'Bill' },
ok: 1 }
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2042 次 |
最近记录: |