如何根据其objectId引用的文档值更新mongodb文档



如何根据其objectId引用的文档值更新MongoDB文档?(我通过猫鼬使用MongoDB(

假设我有两个收藏品。一种叫做比赛,另一种叫做游戏。一场比赛可以有几个游戏。参见下面的代码示例

// competition documents
[
{
compeititionName:"myCompetition",
games:["617...b16", "617...b19", "617...b1c",
competitionStatus:"notStarted",
},
{
compeititionName:"yourCompetition",
games:["617...b18", "617...b19", "617...b1c",
competitionStatus:"playing",
},
{
compeititionName:"ourCompetition",
games:["617...b14", "617...b19", "617...b2b",
competitionStatus:"ended",
}
]

上述competitionStatus取决于比赛中的比赛状态。

如果所有的比赛都没有开始,那么比赛应该将notStarted作为其competitionStatus。然而,如果任何游戏正在进行,或者有一些游戏尚未开始,而其他游戏已完成,则比赛状态应为playing。最后,如果所有比赛都结束了,那么比赛状态应该是ended。游戏收藏的一个例子是:

// game documents
[
{
_id:"617...b16",
gameStatus:"notStarted"
},
{
_id:"617...b18",
gameStatus:"playing"
},
{
_id:"617...b14",
gameStatus:"ended"
},
]

如果游戏的_id状态刚刚更改,我如何更新competitionStatus

因为它是猫鼬,所以您首先选择要更新的模型:

const completion = await CompletionModel.FindOne({games: _id_of_the_game});

然后汇总所有游戏的状态:

const statuses = await GameModel.aggregate([
{$match: {_id: {$in: completion.games}}},
{$group: {_id: gameStatus}}
]).toArray();

然后应用您的业务逻辑设置状态:

if(statuses.leength === 1) { // all games have same status
if(statuses[0]._id === "notStarted") {
completion.competitionStatus = "notStarted";
} elseif (statuses[0]._id === "ended") {
completion.competitionStatus = "ended";
} else {
completion.competitionStatus = "playing";
} else {
completion.competitionStatus = "playing";
}

然后将其保存到数据库:

await completion.save();

请记住,这个伪代码很容易出现竞争条件——如果游戏在aggregate()save()之间更改状态,您可能会在完成文档中得到过时的状态。如果需要,您可能需要添加额外的查询以确保数据的一致性。

更新

如果一个game可以在多个completion中,那么使用Mongoose将是非常低效的。从v4.2开始,您可以使用$merge聚合阶段在数据库端进行所有计算,并更新匹配的文档:

db.competition.aggregate([
{
$match: {
games: "id_of_the_game"
}
},
{
"$lookup": {
from: "games",
let: {
g: "$games"
},
pipeline: [
{
$match: {
$expr: {
$in: [
"$_id",
"$$g"
]
}
}
},
{
$group: {
_id: "$gameStatus"
}
}
],
"as": "statuses"
}
},
{
$set: {
competitionStatus: {
"$cond": {
"if": {
"$gt": [
{
"$size": "$statuses"
},
1
]
},
"then": {
_id: "playing"
},
"else": {
"$arrayElemAt": [
"$statuses",
0
]
}
}
}
}
},
{
"$project": {
competitionStatus: "$competitionStatus._id"
}
},
{
"$merge": {
"into": "competition"
}
}
])

最新更新