You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose中如何实现多字段求和并自动更新总事故统计字段

实现方案

方案1:将总事故数持久化存储到数据库(匹配需求推荐)

第一步:调整Schema定义,新增总事故数字段

const mongoose = require('mongoose')
const accidentSchema = new mongoose.Schema({
  year: { type: Number, required: true },
  // 以下为原有5类事故字段,可替换为你的实际字段命名
  trafficAccident: { type: Number, default: 0 },
  fireAccident: { type: Number, default: 0 },
  workSafetyAccident: { type: Number, default: 0 },
  chemicalLeakAccident: { type: Number, default: 0 },
  otherAccident: { type: Number, default: 0 },
  // 新增总事故数字段
  totalAccidents: { type: Number, default: 0 }
})

第二步:添加save前置钩子,处理新增/全量保存场景

新增文档或者调用save()方法全量更新文档时,会自动触发该钩子计算总和:

accidentSchema.pre('save', function(next) {
  // this指向当前待保存的文档实例
  this.totalAccidents = this.trafficAccident + this.fireAccident + this.workSafetyAccident + this.chemicalLeakAccident + this.otherAccident
  next()
})

第三步:添加更新操作前置钩子,处理部分更新场景

针对updateOne、findOneAndUpdate、updateMany这类不会触发save钩子的更新操作,单独配置计算逻辑:

accidentSchema.pre(['updateOne', 'findOneAndUpdate', 'updateMany'], async function(next) {
  // 拿到查询条件和待更新的字段
  const query = this.getQuery()
  const updateFields = this.getUpdate()
  // 查询现有文档的原始值
  const originDoc = await this.model.findOne(query)
  if (!originDoc) return next()

  // 合并更新值和原始值,计算最新总和
  const finalTraffic = updateFields.trafficAccident ?? originDoc.trafficAccident
  const finalFire = updateFields.fireAccident ?? originDoc.fireAccident
  const finalWork = updateFields.workSafetyAccident ?? originDoc.workSafetyAccident
  const finalChemical = updateFields.chemicalLeakAccident ?? originDoc.chemicalLeakAccident
  const finalOther = updateFields.otherAccident ?? originDoc.otherAccident

  // 把总事故数加入更新字段
  this.set({ totalAccidents: finalTraffic + finalFire + finalWork + finalChemical + finalOther })
  next()
})

注意:如果你的更新操作用到了$inc这类MongoDB操作符,需要额外从updateFields.$inc中提取增量值做计算,适配对应更新场景即可。如果用到批量写入bulkWrite,对应添加pre('bulkWrite')钩子即可。


方案2:虚拟字段动态计算(无需存储,查询时自动生成)

如果你的场景不需要把总事故数持久化到数据库,仅在查询返回时需要该字段,可以用Mongoose虚拟字段实现,无需维护更新逻辑:

// 定义虚拟字段,不会写入数据库
accidentSchema.virtual('totalAccidents').get(function() {
  return this.trafficAccident + this.fireAccident + this.workSafetyAccident + this.chemicalLeakAccident + this.otherAccident
})

// 配置Schema,使JSON输出、toObject转换时自动携带虚拟字段
accidentSchema.set('toJSON', { virtuals: true })
accidentSchema.set('toObject', { virtuals: true })

该方案优势是无需维护自动更新逻辑,劣势是不能直接用totalAccidents字段做数据库查询、排序、聚合操作。

内容的提问来源于stack exchange,提问作者Rajan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 09:36:08