在更新使用Mongoose模型检索并作为承诺处理的文档时遇到问题

跳转到更新#2了解更多细节

我有一个简单的更新问题,通过从Mongoose模型查询容器检索到的文档。 查询查询确实有两个人口,但除此之外,我不知道这个问题可能是什么

我遇到的问题是当我检索一个文档,更新一个属性,然后尝试通过Mongoose Doc.save()方法保存更新到文档,似乎什么也没有发生。 有什么奇怪的是,save()甚至不会传递给它的callback触发..(或者如果我把它作为Promise来处理,则可以触发then()catch()

型号:资产

 module.exports = Mongoose => { const Schema = Mongoose.Schema const assetSchema = new Schema({ attributes: [{ _field: { type: Schema.Types.ObjectId, ref: 'Field', required: true }, value: { type: Schema.Types.Mixed, required: true } }], _partition: { type: Schema.Types.ObjectId, ref: 'Partition' } }) return Mongoose.model( 'Asset', assetSchema ) } 

只是为了一些细节,inheritance人一个例子来自相同的find查询与相同的两个人口

 [ { "_id" : ObjectId("56b626dc4040b5383696d16f"), "_partition" : { _fields: [Object], name: 'Server stuff', _id: ObjectId("56ae4707f3d4645b2e5b0537") }, "attributes" : [ { _field: { _id: ObjectId("56ae4703f3d4645b2e5b0534"), name: 'Hostname' }, value: 'server-04.foobar.ad', _id: ObjectId("56b626dc4040b5383696d172") } ] } ] 

文档查询

下面是我通过Foo.find方法(工作)检索某些文档的位置的代码示例,并更新了第一个属性(我工作)的值,但是当我尝试a.save()文档时。发生:

 Asset .find( { _id: '56b6568cb5195902381f6c65' } ) .populate( { path: 'attributes._field' } ) .populate( { path: '_partition' } ) .then( docs => { if( ! docs ) throw new Error(`No docs were found`) console.log('# Docs Found:', docs.length) // 1 console.log('# Instance?:', docs[0] instanceof Asset) // true console.log('# Docs:', assets) // Shows single document inside array let a = docs[0] a.attributes[0].value = 'blah' // This is where the problem is, nothing below here is displayed in the console a.save(function (err) { if (err) throw new Error('Failed to update:' + err) console.log('Updated!') }) } ) .catch( err => console.error( 'ERROR:',err ) ) .finally( () => Mongoose.connection.close() ) 

在控制台,一切都显示为预期,直到a.save() ..既不是一个错误或Updated! 被展示。

这绝对是一个Mongoose文档,我正在与之交互( a instanceof Foo显示为true),所以我不确定save()没有做什么。

我试图将a.save()作为Promise来处理,而不是将callback交给它,并且再也没有发生任何事情,也没有执行catchcatch

这真让我抓狂!! 林肯定它的东西,我忽略了一些愚蠢的,但我似乎无法find它。 任何帮助将被扣除

PS我没有包含分区字段模型/模式,因为我非常怀疑他们是相关的……但如果有人这样想,只是让我知道

PSS仅供参考,MongoDB用户确实有写入权限

更新#1

根据@JohnnyHK的build议,我试图执行Doc.markModified()

 Asset .find( { _id: '56b6568cb5195902381f6c65' } ) .populate( { path: 'attributes._field' } ) .populate( { path: '_partition' } ) .then( docs => { if( ! docs ) throw new Error(`No docs were found`) console.log('# Docs Found:', docs.length) // 1 console.log('# Instance?:', docs[0] instanceof Asset) // true console.log('# Docs:', assets) // Shows single document inside array let a = docs[0] a.attributes[0].value = 'blah' a.markModified('attributes') // This is where the problem is, nothing below here is displayed in the console a.save(function (err) { if (err) throw new Error('Failed to update:' + err) console.log('Updated!') }) } ) .catch( err => console.error( 'ERROR:',err ) ) .finally( () => Mongoose.connection.close() ) 

没有更改…控制台中显示a.save()没有任何内容,并且文档未更新

更新#2

经过一些修改..它似乎与它是一个承诺有关..

这是成功的

 // AS A CALLBACK Asset.find( { _id: '56b6568cb5195902381f6c65' } ) .populate( { path: 'attributes._field' } ) .populate( { path: '_partition' } ) .exec(function (err, doc) { if (err) throw new Error(err) doc[0].attributes[0].value = 'FOO' doc[0].save(function (err) { if (err) throw new Error(err) console.log('Updated to:',doc[0]) Mongoose.connection.close() }) }) 

这是不成功的

 // AS A PROMISE import Promise from 'bluebird' Mongoose.Promise = Promise // .. Asset.find( { _id: '56b6568cb5195902381f6c65' } ) .populate( { path: 'attributes._field' } ) .populate( { path: '_partition' } ) .then( doc => { doc[0].attributes[0].value = 'FOO' doc[0].save(function (err) { if (err) throw new Error(err) console.log('Updated to:',doc[0]) }) }) .catch( err => { throw new Error(err) }) .finally( () => Mongoose.connection.close() ) 

我能想到的唯一区别是承诺,而不是callback

什么是超级怪异的 …是一些在.then()执行内的代码..只是没有save()

更新#3

我创build了一个github问题 ,并根据我最后一次更新..

我发现这个问题 ,他的“解决scheme”是将整个主版本从4.X降级到3.X。

目前的版本是^ 4.3.7 ,我试图将其更改为3.8.35 ,降级正常,但脚本本身抛出了一堆的错误…诚实地说,id确实不是使用这样一个老版本反正。

我复制了使用您提供的模式并find解决scheme的问题。 以下为我工作和更新.value属性。 尝试预先returndoc[0].save()返回它在本文中提到的

 var mongoose = require('mongoose'); mongoose.Promise = require('bluebird'); // ..... Asset.find( { _id: '56b6568cb5195902381f6c65' } ) .populate( { path: 'attributes._field' } ) .populate( { path: '_partition' } ) .exec() // Queries aren't full-fledged promises! .then( doc => { console.log('Before:',doc[0]); doc[0].attributes[0].value = 'FOO' // Return a promise! return doc[0].save(function(err){ console.log('Updated to:', doc[0]); }); }) .catch( err => { throw new Error(err) }) .finally( () => Mongoose.connection.close() ) 

我也使用.exec()因为根据文档查询不是完整的承诺 (以防万一)。 由于.save()返回一个承诺,你应该返回它,以便承诺顺序解决; 等到之前的承诺完成后再执行。 在这里发布代码