【发布时间】:2014-07-21 09:13:43
【问题描述】:
编辑:解决方案 3(我在使用什么)
db.update(
{
_id: ObjectId("..playerId..."),
"OutstandingRewards.Id": {$all:[Outstanding, Ids, From PHP]}
},
{
$pull: {"OutstandingRewards": {"Id": {$in:[Outstanding, Ids, From PHP]}}},
$addToSet: {"GameObjects":{$each:[New, Rewards, From, PHP]}}
},
);
此原子更新确保我希望声明的所有未完成 ID 在我希望删除它们并将相关的已处理奖励添加到 GameObjects[] 时仍然存在于 OutstandingRewards[] 中。此外,使用$addToSet 运算符可确保不会将重复条目插入GameObjects[]。
解决方案基于下面 Neil Lunn 的回答!
原始问题:
为可领取奖励的游戏编写数据库,数据结构如下:
.
.
"OutstandingRewards" : [
{
"Type" : 0,
"Id" : ObjectId("53c7b54f12727064000000a0")
},
{
"Type" : 1,
"Id" : ObjectId("53c7b54f12727064000000a2")
},
],
"GameObjects":[
{
"Type" : 1,
"Id" : ObjectId("53c7b54f12727064000000a5")
},
{
"Type" : 3,
"Id" : ObjectId("53c7b54f12727064000000a9")
},
],
.
.
我正在尝试实现一个函数,在该函数中,我的 PHP 脚本为玩家想要领取的未完成奖励接收一组 Id,处理奖励项目,并将新处理的条目插入到GameObjects:[]
如果我错了,请纠正我,但由于 $elemMatch 只返回 1 个匹配的元素,我只是执行一个
db.find(
{ _id: ObjectId("..playerId...")},
{_id: 0, "OutstandingRewards": 1, "GameObjects":1}
)
在 PHP 端匹配他们想要索取的所有奖励,并将对象分配给他们。
为了强制执行赋值操作的事务性属性,我想出了 2 个解决方案,并且想知道哪一个在性能方面会更好(或者如果我完全错了,就设计或其他)。
解决方案一:
将整个 GameObject[](可能会变大,100 可能 1,000 个对象)本地存储在 PHP 数组中,将任何声称的奖励附加到该数组并重写整个 GameObject[],同时 OutstandingRewards[] 对象是删除:
db.update({ _id: ObjectId("..playerId...")},
{
$pull: {"OutstandingRewards": {"Id": {$in:$PHPClaimIdsArray}}},
$set: {"GameObjects":$PHPNewRewardsArray}
},
);
我担心这可能会占用大量内存,并且当GameObjects[] 很大时会产生大量冗余写入。
解决方案 2:
对于用户想要领取的每个奖励,执行一次“findAndModify”调用:
db.findAndModify(
query: {
_id: ObjectId("..playerId..."),
"OutstandingRewards": {$elemMatch: {"Id": $rewardId}}
},
update: {
$pull: {"OutstandingRewards": {"Id": $rewardId}},
$push: {"GameObjects":$rewardObject}
}
)
在这种情况下,我担心 PHP - MongoDb 服务器通信和多次写入开销会害死我。
提前致谢!
【问题讨论】:
标签: php mongodb performance mongodb-query