请参阅更新后的示例代码@底部
我用的是猫鼬(太棒了!)在我当前的NodeJS项目中,我有一个MDB集合,它将把文档的更改存储在不同的集合中(基本上是存储所修改的内容的变更量)。
我试图实现的方法是创建一个函数来存储文档的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,并在post保存钩子中看到了该变量的值修改。
因此,我只是将this.toJSON()的值存储在一个变量中,然后在post(保存)钩子中,我试图检索这个文档的缓存版本,并将其与this.toJSON()进行比较。然而,它看起来不像来自pre(save)的文档不包含预修改的数据,它在更新后具有文档的值。
那么,为什么我可以在一个testVar钩子中更新pre(save)的值,而这个更改是从post(save)钩子函数中反映出来的,但是我不能对文档本身做同样的事情?
我在这里想做的事有可能吗?如果是的话,我做错了什么?如果没有-我怎么能做到这一点?
谢谢
更新
根据@Avraam的建议,在通过pre(save)钩子将数据保存到内存中之前,我尝试通过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 )
} )
}下面是更新猫鼬文档的脚本:
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 ) )下面是运行New脚本时的控制台输出:
[QUERY] ORIGINAL value: Revision: 67
[MIDDLEWARE] ORIGINAL value: "Revision: 68"
[MIDDLEWARE] UPDATED value: "Revision: 68"
[QUERY] UPDATED value: Revision: 68如您所见,查询原始值和查询更新值显示有更新。但是中间件的原始/更新值仍然是相同的.所以我仍然不知道为什么
更新
我想也许我可以提供一个更简单但更详细的例子。
下面是中间件模块,它应该比较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发布于 2016-09-30 06:27:36
好的,你问题的第一部分被Avraam Mavridis正确地回答了,所以我将只关注你在问题中的最新更新。
实际上,pre.save 不保存数据库中当前存在的实际文档,而是要保存的文档,并包含对文档所做的更改,即更新的文档。
post.save保存了存储在数据库中的真实文档,因此仍然是更新的版本。因此,在this和post save中,您无法看到所做的更改。
现在,如果您想查看数据库中存在的实际值,则需要在更改和保存数据库之前,即在pre.save中从数据库中获取它。
您可以这样做的一种方法是简单地从数据库查询文档。
var originalDesc
module.exports = ( schema, options ) => {
schema.pre( 'save', function( next ) {
Asset.getAsset( '56d0819b655baf4a4a7f9cad' )
.then( assetDoc => {
originalDesc = assetDoc.attributes[1].value;
console.log( '[MIDDLEWARE ORIGINAL Desc]\n\t', originalDesc )
next()
} );
} );
schema.post( 'save', function( ) {
var newDesc = this.toJSON().attributes[1].value
console.log( '[MIDDLEWARE NEW Desc]\n\t', newDesc)
} )
}
还有一种使用自定义setter的替代方法,而且已经有一个很好的answer here,但是这需要为每个属性设置一个自定义设置器。
schema.path('name').set(function (newVal) {
this.originalDesc = this.Description;
});
schema.pre('save', function (next) {
console.log( '[MIDDLEWARE ORIGINAL Desc]\n\t', this.originalDesc )
next();
})
schema.post( 'save', function( ) {
var newDesc = this.toJSON().attributes[1].value
console.log( '[MIDDLEWARE NEW Desc]\n\t', newDesc)
} )希望这能有所帮助。
发布于 2016-09-23 10:34:20
origDocument具有对this.toJSON()的引用,当您调用console.log时,引用点已经更改的实际对象的值。使用类似于JSON.stringify的方法来比较这些值。
origDocument = JSON.stringify( this.toJSON() )
发布于 2016-09-24 06:45:20
我想你误解了猫鼬的前/后挂钩是怎么工作的。当您抓取文档(就像您正在做的那样)并重新保存它时。它将不包含文档中最初的任何变量。它将拥有目前在文件中的任何内容。
所以,你要这么做:
我认为您要做的是在模式上实现一个实例方法,您可以使用该方法来定义所需的逻辑。在调用.save()之前调用它(或者在执行自己的逻辑之后使用它只调用.save() )
示例:
schema.methods.createRevisionHistory= function(object, callback) {
// Do comparison logic between this. and object.
// modify document (this) accordingly
// this.save(function(err, doc) {
// if(err)
// return callback(err)
// callback(doc);
// })
};希望这能有所帮助
阅读更多:http://mongoosejs.com/docs/guide.html#methods
https://stackoverflow.com/questions/39654777
复制相似问题