作者:ShaileshShekhawat映射(ORM)技术简介随着程序的增长,日志记录成为跟踪一切的关键部分。这对于调试目的尤其重要。现在有一个npm的日志记录模块。这些模块可以将日志存储在不同格式或级别的文件中。我们将使用流行的ORMMongoose讨论Node.jsExpress程序中的API日志记录。那么如何创建一个Mongoose插件,以更清晰的方式为您进行日志记录并简化API日志记录呢?Mongoose中的插件是什么?在Mongoose中,模式是可插入的。插件就像一个函数,您可以在模式中使用它并在模式实例上一次又一次地重复使用它。Mongoose还提供了可用于所有模式的全局插件。例如,我们将编写一个插件,它将创建两个json的差异并写入mongodb。第1步:创建一个基本的日志模式模型让我们创建一个具有以下六个属性的基本日志模式:操作:顾名思义,这是API的操作过程,可以是创建、更新、删除或其他。类别:API类别。比如医生和病人。它更像是一个班级。CreatedBy:正在使用或调用API的用户。消息:您可以在此处包含您想要显示的任何类型的消息,这些消息在调试过程中是有意义的或有帮助的。Diff:这是主要的属性,它是两个JSON的diff如果你想对自己的应用有意义,你可以添加更多的字段,你也可以根据需要更改和升级架构。这是我们的模型:models/log.jsconstmongoose=require('mongoose')constSchema=mongoose.Schemaconst{ObjectId}=SchemaconstLogSchema=newSchema({action:{type:String,required:true},category:{type:String,required:true},createdBy:{type:ObjectId,ref:'Account',required:true},message:{type:String,required:true},diff:{type:Schema.Types}.Mixed},},{时间戳:{createdAt:'createdAt',updatedAt:'updatedAt'},})LogSchema.index({action:1,category:1})module.exports=mongoose.model('Log',LogSchema)第2步:编写一个函数来获取2个JSON之间的差异因此,下一步是您需要一个可重用的函数来动态创建两个JSON的差异。让我们调用diff.jsconst_=require('lodash')exports.getDiff=(curr,prev)=>{functionchanges(object,base){return_.transform(object,(result,value,key)=>{if(!_.isEqual(value,base[key]))result[key]=(_.isObject(value)&&_.isObject(base[key]))?changes(value,base[key]):value})}returnchanges(curr,prev)}我使用了lodash,一个提供相同功能的流行库。让我们分解上面的函数,看看发生了什么:_.transform:它是数组的.reduce的替代品。它遍历对象的键和值。它提供一个累加器作为第一个参数。结果是一个累加器并且是可变的。_.isEqual:对两个值进行深度比较以确定它们是否相等。isEqual:此方法支持比较数组、数组缓冲区、布尔值、日期对象、错误对象、映射、数字、对象、正则表达式、集合、字符串、符号和类型化数组。对象通过它们自己的方法进行比较,而不是通过继承的、可枚举的属性进行比较。比较函数和DOM节点是否严格相等,即使用===。这里我们遍历每个对象的属性和值,并将其与旧对象进行比较。如果当前对象的值不等于前一个对象中相同属性的值:base[key]如果该值是对象本身,我们递归调用函数更改直到它得到一个值,最终将存储为结果[键]=结果中的值。第3步:创建一个diff插件并将其保存到数据库现在我们需要跟踪数据库中的先前文档并在将其保存到mongodb之前创建一个diff。const_=require('lodash')constLogSchema=require('../models/log')const{getDiff}=require('../utils/diff')constplugin=function(schema){schema.post('init',doc=>{doc._original=doc.toObject({transform:false})})schema.pre('save',function(next){if(this.isNew){next()}else{this._diff=getDiff(this,this._original)next()}})schema.methods.log=function(data){data.diff={之前:this._original,之后:this._diff,}returnLogSchema.create(data)}}module.exports=plugin在Mongoose中,有不同的钩子可用。现在我们需要使用架构上可用的init和save方法。this.isNew():如果你正在创建一个新文档,那么只需返回next()中间件。在schema.post('init')的toObject()中:doc._original=doc.toObject({transform:false})MongooseModel继承自document,它有一个toObject()方法。它将文档转换为Object()和transform:false是不允许转换返回对象。第4步:用法-如何在express.jsAPI中使用在您的主server.js或app.js中:初始化全局插件,以便它可用于所有模式。您还可以通过在架构模型中对其进行初始化,将其用于特定架构。constmongoose=require('mongoose')mongoose.plugin(require('./app/utils/diff-plugin'))这是用户更新API的基本示例:constUser=require('../models/user')exports.updateUser=(req,res,next)=>{returnUser.findById(req.params.id).then(user=>{if(!user)thrownewError('目标用户不存在.更新失败。')const{name}=req.bodyif(name)user.name=namereturnuser.save()}).then(result=>{res.json(result)returnresult})。catch(next).then(user=>{if(user&&typeofuser.log==='function'){constdata={action:'update-user',category:'users',createdBy:req.user.id,message:'Updatedusername',}returnuser.log(data)}}).catch(err=>{console.log('Caughterrorwhilelogging:',err)})}本教程的结论,您学习了如何创建Mongoose插件并使用它记录API中的更改,您可以使用插件做更多事情来构建健壮的Node.js程序。
