我正在将Meteor与MongoDB结合使用,并且我在后台运行的批处理更新似乎有问题。定期运行一个作业,该作业遍历一个集合中的所有元素并进行更新。它应该更新或添加,但是它会重复字段。
我编写了一些辅助函数,这些函数应确保仅获取可用资源并正确更新集合:
static getStore(warehouse, resource) {
return warehouse.storage.find(x => x.resource == resource)
}
static getStoreAmount(warehouse, resource) {
let store = this.getStore(warehouse, resource)
if (store) {
return store.amount
} else {
return 0
}
}
static addToStorage(warehouse, resource, amount) {
if (amount <= 0) return true;
console.log("adding "+amount+" "+resource)
let store = this.getStore(warehouse, resource)
// TODO: check if enough storage space is left
// FIXME: somehow, something created a duplicate entry for grain here (from 2 fields) - async database calls?
// with 3 fields, it gets added 3 times - definitely reliably bugged :-(
// FIXME: somehow, despite adding twice, nothign was left - again async update call just before $pull'ing it?
if (store) {
Warehouses.update({"_id":warehouse._id, "storage.resource": resource}, {
$set: {
"storage.$.amount": store.amount + amount
}
})
} else {
Warehouses.update({"_id":warehouse._id}, {
$push: {
storage: {
resource: resource,
amount: amount,
buy: { amount: 0, price: 0 },
sell: { amount: 0, price: 0 }
}
}
})
}
return true
}
static checkTakeFromStorage(warehouse, resource, amount, min=1) {
if (amount <= 0) return 0;
let have = this.getStoreAmount(warehouse,resource)
if (have < min) {
return 0
}
console.log("taking "+amount+" "+resource)
if (amount >= have) {
// FIXME: don't pull if we have buy or sell values !
amount = have
// $pull is tricky because of meteor limitations, so here is a workaround I found on the Internet:
let raw = Warehouses.rawCollection()
let findOneAndUpdate = Meteor.wrapAsync(raw.findOneAndUpdate, raw)
findOneAndUpdate({_id: warehouse._id}, {
$pull: { storage: { resource: resource }}
})
} else {
Warehouses.update({"_id":warehouse._id, "storage.resource": resource}, {
$set: {
"storage.$.amount": have - amount
}
})
}
return amount
}
数据结构如下:
warehouses {
...various things...
storage: [
{ resource: "a", amount: 123 },
{ resource: "b", amount: 456 },
...
]
}
但是,当我运行批处理作业时,与我想要的代码相反,在存储表中为同一资源创建了多个条目。我可能以一种愚蠢的方式进行更新,并且可能有一种适当的流星/蒙哥方式来确保不会发生这种情况,但是由于我进行了更新,因此我在搜索时找不到它嵌入式文档中的数组。