更新使用 Mongoose 模型检索并作为承诺处理的文档时出现问题
Having issues updating a document thats retrieved using a Mongoose model and processed as a promise
跳转到更新 #2 以获得更详细的信息
我在对通过 Mongoose 模型查询容器检索到的文档进行简单更新时遇到问题。 find
查询确实有两个总体,但除此之外,我不确定问题可能是什么
我 运行 遇到的问题是,当我检索文档时,更新 属性,然后尝试通过 Mongooses Doc.save()
方法将更新保存到文档,似乎什么都没有发生。奇怪的是,save() 是否甚至没有触发传递给它的回调..(或者如果我将其作为 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 )
}
这里是一个示例结果,来自相同的 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
显示为真),所以我完全不确定为什么 save() 没有做任何事情..
我尝试将 a.save()
作为一个 Promise 来处理,而不是将回调传递给它,同样,什么也没有发生,then
或 catch
都没有被执行。
这让我发疯!!我确定它是我忽略的一些愚蠢的东西,但我似乎无法找到它。任何帮助将不胜感激
P.S. 我没有包含 Partition 或 Field models/schemas 因为我非常怀疑他们之间是否有关联...但是如果有人这么认为,请告诉我
P.S.S. 仅供参考,MongoDB 用户 具有写入权限
更新#1
根据@JohnnyHK 的建议,我尝试执行 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() )
我能想到的唯一区别是承诺,而不是回调
什么超级奇怪...是.then()
执行的一些代码..只是不是save()
更新#3
我创建了一个 github issue,根据我上次的更新..
我发现 this issue,他的 "solution" 是将整个主要版本从 4.X 降级到 3.X...
我现在的版本是^4.3.7,我试着改成3.8.35,降级了很好,但是脚本本身抛出了一堆错误...老实说,我宁愿不使用这么旧的版本。
我使用您提供的模式复制了您遇到的问题并找到了解决方案。以下对我有用并更新了 .value
属性。尝试将 return
添加到 doc[0].save()
到 return 之前,如 this article
中所述
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()
因为根据文档 queries aren't full-fledged promises (just in case). Since .save()
returns a promise, you should return it so that the promises resolve sequentially; waiting until previous promises complete before executing. Posted the code here
跳转到更新 #2 以获得更详细的信息
我在对通过 Mongoose 模型查询容器检索到的文档进行简单更新时遇到问题。 find
查询确实有两个总体,但除此之外,我不确定问题可能是什么
我 运行 遇到的问题是,当我检索文档时,更新 属性,然后尝试通过 Mongooses Doc.save()
方法将更新保存到文档,似乎什么都没有发生。奇怪的是,save() 是否甚至没有触发传递给它的回调..(或者如果我将其作为 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 )
}
这里是一个示例结果,来自相同的 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
显示为真),所以我完全不确定为什么 save() 没有做任何事情..
我尝试将 a.save()
作为一个 Promise 来处理,而不是将回调传递给它,同样,什么也没有发生,then
或 catch
都没有被执行。
这让我发疯!!我确定它是我忽略的一些愚蠢的东西,但我似乎无法找到它。任何帮助将不胜感激
P.S. 我没有包含 Partition 或 Field models/schemas 因为我非常怀疑他们之间是否有关联...但是如果有人这么认为,请告诉我
P.S.S. 仅供参考,MongoDB 用户 具有写入权限
更新#1
根据@JohnnyHK 的建议,我尝试执行 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() )
我能想到的唯一区别是承诺,而不是回调
什么超级奇怪...是.then()
执行的一些代码..只是不是save()
更新#3
我创建了一个 github issue,根据我上次的更新..
我发现 this issue,他的 "solution" 是将整个主要版本从 4.X 降级到 3.X...
我现在的版本是^4.3.7,我试着改成3.8.35,降级了很好,但是脚本本身抛出了一堆错误...老实说,我宁愿不使用这么旧的版本。
我使用您提供的模式复制了您遇到的问题并找到了解决方案。以下对我有用并更新了 .value
属性。尝试将 return
添加到 doc[0].save()
到 return 之前,如 this article
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()
因为根据文档 queries aren't full-fledged promises (just in case). Since .save()
returns a promise, you should return it so that the promises resolve sequentially; waiting until previous promises complete before executing. Posted the code here