首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mongoose中间件方法之间的数据共享--预保存和后保存

Mongoose中间件方法之间的数据共享--预保存和后保存
EN

Stack Overflow用户
提问于 2016-09-23 07:12:12
回答 6查看 8.7K关注 0票数 15

请参阅更新后的示例代码@底部

我用的是猫鼬(太棒了!)在我当前的NodeJS项目中,我有一个MDB集合,它将把文档的更改存储在不同的集合中(基本上是存储所修改的内容的变更量)。

我试图实现的方法是创建一个函数来存储文档的JSON版本,这是通过pre('save')钩子完成的。然后创建另一个钩子,通过post('save')执行,以比较存储在pre('save')中的数据,并将其与文档新数据进行比较。

以下是我到目前为止所拥有的:

代码语言:javascript
复制
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)中执行相同的操作,如下所示:

代码语言:javascript
复制
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 )
    } )
}

下面是更新猫鼬文档的脚本:

代码语言:javascript
复制
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脚本时的控制台输出:

代码语言:javascript
复制
[QUERY] ORIGINAL value: Revision: 67
[MIDDLEWARE] ORIGINAL value: "Revision: 68"
[MIDDLEWARE] UPDATED value: "Revision: 68"
[QUERY] UPDATED value: Revision: 68

如您所见,查询原始值和查询更新值显示有更新。但是中间件的原始/更新值仍然是相同的.所以我仍然不知道为什么

更新

我想也许我可以提供一个更简单但更详细的例子。

下面是中间件模块,它应该比较pre(save)

post(save):“严格使用”

代码语言:javascript
复制
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属性的代码.

代码语言:javascript
复制
'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
EN

回答 6

Stack Overflow用户

发布于 2016-09-30 06:27:36

好的,你问题的第一部分被Avraam Mavridis正确地回答了,所以我将只关注你在问题中的最新更新。

实际上,pre.save 不保存数据库中当前存在的实际文档,而是要保存的文档,并包含对文档所做的更改,即更新的文档。

post.save保存了存储在数据库中的真实文档,因此仍然是更新的版本。因此,在thispost save中,您无法看到所做的更改。

现在,如果您想查看数据库中存在的实际值,则需要在更改和保存数据库之前,即在pre.save中从数据库中获取它。

您可以这样做的一种方法是简单地从数据库查询文档。

代码语言:javascript
复制
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,但是这需要为每个属性设置一个自定义设置器。

代码语言:javascript
复制
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)
} )

希望这能有所帮助。

票数 3
EN

Stack Overflow用户

发布于 2016-09-23 10:34:20

origDocument具有对this.toJSON()的引用,当您调用console.log时,引用点已经更改的实际对象的值。使用类似于JSON.stringify的方法来比较这些值。

origDocument = JSON.stringify( this.toJSON() )

票数 0
EN

Stack Overflow用户

发布于 2016-09-24 06:45:20

我想你误解了猫鼬的前/后挂钩是怎么工作的。当您抓取文档(就像您正在做的那样)并重新保存它时。它将不包含文档中最初的任何变量。它将拥有目前在文件中的任何内容。

所以,你要这么做:

  1. 抓取文件(67)
  2. 修改文档<(您在这里做了+1 )(现在是68)
  3. Document.Save()调用
  4. 预保存打印当前文档(68)
  5. 保存后打印出当前文档(68)

我认为您要做的是在模式上实现一个实例方法,您可以使用该方法来定义所需的逻辑。在调用.save()之前调用它(或者在执行自己的逻辑之后使用它只调用.save() )

示例:

代码语言:javascript
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39654777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档