什么是免费更改mongodb中所有记录值的最有效方法



假设我有一个如下的模型

import {model, Schema, Types} from 'mongoose'
import { IResource } from '../interfaces'
const ResourceSchema = new Schema<IResource>({
user : {type : Schema.Types.ObjectId, ref : 'users'},
type : {type: Schema.Types.ObjectId , ref : 'resource_datas'},
building : {type : Schema.Types.ObjectId , ref : 'buildings'},
lastUpdate : {type : Date , default : Date.now},
value : {type : Number, default : 500},
valuePerHours : {type : Number, default : 0}
})
const Resources = model<IResource>('resources' , ResourceSchema)
export default Resources

样本记录:

[
{
user : User_ID,
type : Type_ID,
building : Building_ID,
lastUpdate : Date("2022-03-21T08:32:40.866+00:00"),
value : 500,
valuePerHours : 120
},
{
user : User_ID,
type : Type_ID,
building : Building_ID,
lastUpdate : Date("2022-03-21T08:22:40.866+00:00"),
value : 540,
valuePerHours : 150
},
{
user : User_ID,
type : Type_ID,
building : Building_ID,
lastUpdate : Date("2022-03-21T08:36:40.866+00:00"),
value : 1200,
valuePerHours : 180
},
]

如何更新字段";值";尽可能经常?

目前,我确实喜欢下面的

while (true) {
const resources = await Resources.find({})
.limit(100)
.sort({lastUpdate : 1})
.populate('building')
const promiseSave = []
for (let index = 0; index < resources.length; index++) {
const resource = resources[index];
const now = Date.now()
const diffTime = (now - new Date(resource.lastUpdate).getTime()) / 1000
const percentDiffTimePerHour = diffTime / 3600000
const generate = resource.valuePerHours
const valueAfterDiff = generate * percentDiffTimePerHour
resource.value += valueAfterDiff
resource.lastUpdate = now         
promiseSave.push(resource.save())
}
await Promise.all(promiseSave)
}
//update value follow lastUpdate and valuePerHours 

每轮查找100条记录并保存,耗时约200ms如果我有100万条记录,更新所有记录需要2000秒。我可以每小时或每天更新一次。但更好的是,它应该几乎";实时";。有更好的方法吗?感谢阅读。

您不需要任何循环或花哨的逻辑。您可以运行一个简单的更新聚合管道:

db.Resources.updateMany({}, [
{
$set: {
lastUpdate: "$$NOW",
value: {
$sum: ["$value", {
$multiply: [{
$divide: [
{ $dateDiff: { startDate: "$lastUpdate", endDate: "$$NOW", unit: "second" } },
60 * 60 * 1000
]
}, "$valuePerHours"]
}]
}
}
}
])

或者短一点:

db.Resources.updateMany({}, [
{
$set: {
lastUpdate: "$$NOW",
value: {
$sum: ["$value", {
$multiply: [
{ $dateDiff: { startDate: "$lastUpdate", endDate: "$$NOW", unit: "second" } },
"$valuePerHours",
1 / 60 / 60 / 1000
]
}]
}
}
}
])

这将更新分辨率为秒的value。如果您需要毫秒的分辨率,请使用

db.Resources.updateMany({}, [
{
$set: {
lastUpdate: "$$NOW",
value: {
$sum: ["$value", {
$multiply: [{
$divide: [
{ $dateDiff: { startDate: "$lastUpdate", endDate: "$$NOW", unit: "millisecond" } },
60 * 60 * 1000 * 1000
]
}, "$valuePerHours"]
}]
}
}
}
])

最新更新