【发布时间】:2017-01-31 23:02:51
【问题描述】:
在底部查看更新的示例代码
我在当前的 NodeJS 项目中使用 Mongoose(顺便说一句,这很棒!),并且我有一个 MDB 集合,它将将文档的更改存储在不同的集合中(基本上是一个 changelog存储修改过的内容)
我试图实现的方法是创建一个函数来存储文档的 JSON 版本,这是通过 pre('save') 钩子完成的。然后创建另一个钩子,通过post('save')执行,比较pre('save')中存储的数据,并将其与文档新数据进行比较。
这是我目前所拥有的:
var origDocument
var testVar = 'Goodbye World'
module.exports = ( schema, options ) => {
schema.pre( 'save', function( next ) {
// Store the original value of the documents attrCache.Description value
origDocument = this.toJSON().attrCache.Description
// Change the testVar value to see if the change is reflected in post(save)
testVar = 'Hello World'
next()
} )
schema.post( 'save', function( ) {
// Attempt to compare the documents previous value of attrCache.Description, with the new value
console.log("BEFORE:", origDocument)
console.log("AFTER:", this.toJSON().attrCache.Description)
// Both of the above values are the same! >.<
console.log('post(save):',testVar) // result: post(save):Hello World
// But the above works just fine..
} )
}
我原本认为这行不通。为了测试这两个钩子是否在同一范围内执行,我在页面顶部创建了一个名为 testVar 的测试变量,带有一些任意值,然后在 post(save) 钩子中检索了 testVar 和值该变量的修改在保存后挂钩中可见。
所以从那里,我只是将this.toJSON() 的值存储在一个变量中,然后在 post(save) 挂钩中,我试图检索此文档的缓存版本,并将其与this.toJSON() 进行比较。但是,pre(save) 中的文档看起来并不包含修改前的数据,它在某种程度上具有文档的价值在它被更新之后。
那么,为什么我可以从 pre(save) 挂钩中更新 testVar 的值,而这种更改反映在 post(save) 挂钩函数中,但我不能对文档本身做同样的事情?
我在这里尝试做的事情是否可能?如果是这样,我做错了什么?如果没有 - 我该如何做到这一点?
谢谢
更新
根据@Avraam 的建议,我尝试通过JSON.stringify() 运行数据,然后通过pre(save) 挂钩将其保存在内存中,然后在post(save) 中执行相同操作,如下所示:
var origDocument
module.exports = ( schema, options ) => {
schema.pre( 'save', function( next ) {
origDocument = JSON.stringify( this.toJSON().attributes[1].value )
// Should store and output the CURRENT value as it was before the
// document update... but it displays the NEW value somehow
console.log( '[MIDDLEWARE] ORIGINAL value:', origDocument )
next()
} )
schema.post( 'save', function( ) {
var newDocument = JSON.stringify(this.toJSON().attributes[1].value)
console.log( '[MIDDLEWARE] UPDATED value:', newDocument )
} )
}
下面是更新 mongoose 文档的脚本:
Asset.getAsset( '56d0819b655baf4a4a7f9cad' )
.then( assetDoc => {
// Display original value of attribute
console.log('[QUERY] ORIGINAL value:', assetDoc.attributes[1].value)
var updateNum = parseInt( assetDoc.__v )+1
assetDoc.attr('Description').set('Revision: ' + updateNum )
return assetDoc.save()
} )
.then(data => {
// Display the new value of the attribute
console.log('[QUERY] UPDATED value:', data.attributes[1].value)
//console.log('DONE')
})
.catch( err => console.error( 'ERROR:',err ) )
这是我运行新脚本时的控制台输出:
[QUERY] ORIGINAL value: Revision: 67
[MIDDLEWARE] ORIGINAL value: "Revision: 68"
[MIDDLEWARE] UPDATED value: "Revision: 68"
[QUERY] UPDATED value: Revision: 68
如您所见,[QUERY] ORIGINAL 值和 [QUERY] UPDATED 值表明有更新。但是 [MIDDLEWARE] 原始/更新的值仍然相同......所以我仍然坚持为什么
更新
我想也许我可以提供一个更简化但更详细的示例。
这是应该比较 pre(save) 和
post(save):
'使用严格'
import _ from 'moar-lodash'
import * as appRoot from 'app-root-path'
import Mongoose from 'mongoose'
import diff from 'deep-diff'
var originalDesc
module.exports = ( schema, options ) => {
schema.pre( 'save', function( next ) {
originalDesc = JSON.parse( JSON.stringify( this.toJSON() ) ).attributes[1].value
console.log( '[MIDDLEWARE ORIGINAL Desc]\n\t', originalDesc )
next()
} )
schema.post( 'save', function( ) {
var newDesc = JSON.parse( JSON.stringify( this.toJSON() ) ).attributes[1].value
console.log( '[MIDDLEWARE NEW Desc]\n\t', newDesc)
} )
}
然后是使用Asset 模型并更新Description 属性的代码...
'use strict'
import _ from 'moar-lodash'
import Promise from 'bluebird'
import Mongoose from 'mongoose'
import Async from 'async'
import Util from 'util'
import * as appRoot from 'app-root-path'
Mongoose.Promise = Promise
Mongoose.connect( appRoot.require('./dist/lib/config').database.connection )
const accountLib = appRoot.require('./dist/lib/account')
const models = require( '../models' )( Mongoose )
models.Asset.getAsset( '56d0819b655baf4a4a7f9cad' )
.then( assetDoc => {
var jqDoc = JSON.parse(JSON.stringify(assetDoc.toJSON()))
// Show the CURRENT description
console.log('[IN QUERY - Before Modify]\n\t', jqDoc.attributes[1].value)
assetDoc.attr('Description').set( 'Date-'+Date.now() )
return assetDoc.save()
} )
.then(data => {
// Just show the Description AFTER it was saved
console.log('[AFTER QUERY - AFTER Modify]\n\t', data.attributes[1].value)
})
.catch( err => console.error( 'ERROR:',err ) )
.finally( () => {
Mongoose.connection.close()
console.log('# Connection Closed')
})
[IN QUERY - Before Modify]
Date-1474915946697
[MIDDLEWARE ORIGINAL Desc]
Date-1474916372134
[MIDDLEWARE NEW Desc]
Date-1474916372134
[AFTER QUERY - AFTER Modify]
Date-1474916372134
# Connection Closed
【问题讨论】:
-
我真的无法在第一个控制台输出(最后一个 sn-p 的第一行)中得到它的原因,但是在 post 中间件挂钩的功能下,它没有
-
console.log( '[MIDDLEWARE ORIGINAL Desc]\n\t', this. attributes )和console.log( '[MIDDLEWARE NEW Desc]\n\t', this.attributes)显示什么? -
@Justin 您是否真的想要两个版本的数据,或者您想知道某个属性是否已更改?
标签: javascript node.js mongodb mongoose mongoose-schema