4

跳转到更新 #2 以获得更详细的信息

我对通过 Mongoose 模型查询容器检索到的文档进行简单更新时遇到问题。该find查询确实有两个群体,但除此之外,我不确定问题可能是什么

我遇到的问题是,当我检索文档,更新属性,然后尝试通过 MongoosesDoc.save()方法将更新保存到文档时,似乎什么也没发生。奇怪的是,save() 甚至没有触发传递给它的回调..(或者触发then()或者catch()如果我将其作为 Promise 处理)

型号:资产

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 进行处理,而不是对其进行回调,然后再一次,什么也没发生,thenor也没有catch被执行。

这真让我抓狂!!我确定它是我忽略的一些愚蠢的东西,但我似乎找不到它。任何帮助将不胜感激

PS我没有包括分区字段模型/模式,因为我非常怀疑它们是否相关......但如果有人这么认为,请告诉我

PSS仅供参考,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 问题,并且根据我上次的更新..

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

我当前的版本是^4.3.7,我尝试将其更改为3.8.35,降级顺利,但脚本本身引发了一堆错误......老实说,id 真的不使用这么旧的反正版本。

4

1 回答 1

1

我使用您提供的架构复制了您遇到的问题并找到了解决方案。以下对我有用并更新了.value属性。尝试return按照本文doc[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()返回一个承诺,您应该返回它,以便承诺按顺序解决;等到之前的承诺完成后再执行。在这里发布代码

于 2016-02-08T21:26:31.310 回答