我的mongodb更新中的比赛条件? (使用流星)

时间:2018-07-16 04:25:42

标签: mongodb meteor

我正在将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 },
...
]
}

但是,当我运行批处理作业时,与我想要的代码相反,在存储表中为同一资源创建了多个条目。我可能以一种愚蠢的方式进行更新,并且可能有一种适当的流星/蒙哥方式来确保不会发生这种情况,但是由于我进行了更新,因此我在搜索时找不到它嵌入式文档中的数组。

0 个答案:

没有答案