在 Mongoose 中间件方法之间共享数据 pre save 和 post save

2024-04-01

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

我在当前的 NodeJS 项目中使用 Mongoose(顺便说一句,这非常棒!),并且我有一个 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,以及该变量的值修改was seen在帖子保存挂钩中。

所以从那里开始,我只是存储了this.toJSON()在一个变量中,然后在 post(save) 挂钩中,我尝试检索该文档的缓存版本,并将其与this.toJSON()。然而,它看起来并不像来自pre(save)不保存预先修改的数据,它以某种方式具有文档的价值after它已更新。

那么为什么我可以更新的值testVar从一个内pre(save)钩子,并且该变化反映在post(save)钩子函数,但我不能对文档本身做同样的事情?

我在这里尝试做的事情可能吗?如果是这样,我做错了什么?如果没有 - 我怎样才能做到这一点?

谢谢

Update

根据@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

如您所见,[查询] 原文值和[查询] 已更新值表明有更新。但是[中间件]原始/更新后的值仍然相同......所以我仍然不知道为什么

UPDATE

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

这是应该比较的中间件模块pre(save) and

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

好的,您问题的第一部分已由 Avraam Mavridis 正确回答 所以我只会关注你在问题中的最后更新。

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

post.save保存存储在数据库中的真实文档,因此仍然是更新的版本。所以你看不到所做的改变this同时pre and post save.

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


One way you could do this is simply query the document from database
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)
    } )
}

There is an alternative way than this using custom setter, and there is already a good answer here https://stackoverflow.com/a/11546870/3556874, but this would require to set a custom setter for each property
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)
} )

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Mongoose 中间件方法之间共享数据 pre save 和 post save 的相关文章

随机推荐

  • 部分类构造函数

    有没有办法让分部类的构造函数调用我的或可能未定义的另一个方法 基本上我的部分类构造函数是这样定义的 public partial class Test public Test do stuff 我希望能够以某种方式插入在调用类构造函数后运行
  • java.lang.ClassCastException:字符串无法转换为日期

    堆栈跟踪 java lang ClassCastException java lang String cannot be cast to java util Date at org hibernate type descriptor jav
  • 检查应用程序范围书签下的路径在沙盒应用程序内是否可写

    我有一个 OS X 应用程序 它存储应用程序范围的书签以持久访问某些目录 我可以毫无问题地写入这些目录 但我的代码中有一部分我想进行额外的检查以确认路径可写并且失败 var fileManager NSFileManager NSFileM
  • AVFoundation 将 Alpha 通道视频叠加在另一个视频上?

    我尝试过将图像覆盖在视频资源上 并且还认为应该有某种方法可以将 Alpha 通道视频覆盖在另一个视频上 有没有办法将 Alpha 通道视频叠加在另一个视频资源上 None
  • 奇怪的 Java HashMap 行为 - 找不到匹配的对象

    当我试图在里面寻找钥匙时 我遇到了一些奇怪的行为java util HashMap 我想我错过了一些东西 代码段基本上是 HashMap
  • 膨胀类 ImageButton 时出错

    我有一个应用程序 其中有fragment and image button关于这一点 问题是它正在上面工作5 0但不低于5 0 最小sdk版本是17 不明白这里出了什么问题 我遇到了 2 个例外 One is RuntimeExceptio
  • Checkstyle Eclipse 插件不起作用

    我正在使用 Juno Eclipse 发行版的 eclipse checkstyle 插件 每当检查代码是否有 checkstyle 错误时 我都会收到以下错误 cannot initialize module TreeWalker Una
  • 使用 Scala 进行依赖注入

    我正在寻找一种在 Scala 中进行依赖注入的方法 类似于 C 中的 Spring 或 Unity 但我没有发现任何真正有趣的东西 MacWire 我不明白这样做有什么好处 因为我们必须在wire CASS 中上课 那么如果你在调用wire
  • nginx conf 文件是什么语言?

    我想在我的 Nginx 配置文件中编写一些更复杂的条件 但我不确定语法 也找不到描述示例中基础知识之外可以做什么的文档 而且我似乎无法在Nginx 论坛或邮件列表 例如 我是否可以拥有一个unless健康 状况 所以我是 nginx 的新手
  • 如何以编程方式运行 NUnit

    我有一些引用 NUnit 的程序集并使用单个测试方法创建单个测试类 我能够获取该程序集的文件系统路径 例如 C test dll 我想以编程方式使用 NUnit 来针对该程序集运行 到目前为止我有 var runner new Simple
  • 我无法打开可变文件名

    有什么理由吗Dev C 不让我做file open file name variable 我不明白为什么它不允许我打开任何东西 除了像这样的硬编码名称file open abc txt 如何解决这个问题 不使用 Dev C 这基本上是我所拥
  • DecimalFormat 的奇数结果四舍五入

    提供一个浮点值37 35我得到一串37 3 这是我的代码 DecimalFormat format new DecimalFormat 0 format setRoundingMode RoundingMode HALF UP return
  • C# 剪贴板直接复制粘贴

    Hi 我想直接复制 粘贴 例如我只需单击一下按钮即可将粘贴到剪贴板 为此您可以编写示例代码 如果您想从文本框 在此示例中为 textBox1 复制 则需要以下内容 Clipboard SetText textBox1 Text To cop
  • 无法移出 ViewPort 窗格 - Selenium

    我正在尝试使网页自动化 http the internet herokuapp com exit intent http the internet herokuapp com exit intent 如果我们从视图窗格移向页面顶部 则会出现
  • 防止一个元素覆盖另一个元素[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有一个固定的标题 当我滚动时 某些
  • 如何在.net中检索硬盘固件序列号?

    如何在 net 中检索硬盘固件序列号 我能够使用 WMI 调用检索 HDD 序列号 但无法找到任何方法来检索 HDD 固件序列号 提前感谢 使用 WMI 简单来说 这是一个低级函数 没有 理智的 更高级别的 API 会支持 读取或写入文件是
  • 什么是 F# 引号?

    F 中的 引号 是什么 它们的用途是什么 See http msdn microsoft com en us library dd233212 aspx http msdn microsoft com en us library dd233
  • Rails 5.2.0 与 Ruby 2.5.1 控制台 - `警告:``已经`初始化常量 FileUtils::VERSION

    我目前在新的 Rails 应用程序中遇到问题 更具体地说 轨道 5 2 0 Ruby 2 5 1p57 2018 03 29 修订版 63029 x86 64 darwin17 rvm 1 29 4 最新 作者 Michal Papis P
  • 将日期字符串解析为 java.util.Date 时出现非法模式字符“T”

    我有一个日期字符串 我想使用 java Date API 将其解析为正常日期 以下是我的代码 public static void main String args String date 2010 10 02T12 23 23Z Stri
  • 在 Mongoose 中间件方法之间共享数据 pre save 和 post save

    请参阅底部更新的示例代码 我在当前的 NodeJS 项目中使用 Mongoose 顺便说一句 这非常棒 并且我有一个 MDB 集合 它将在不同的集合中存储文档的更改 基本上是一个变更日志存储修改的内容 我试图实现的方法是创建一个存储文档的