我希望能够获取某些值,并根据哪个键具有特定ID来获取这些值在集合中的次数。例如,这是来自游戏日志集合
的单个文档的示例{
"_id": "5af88940b73b2936dcb6dfdb",
"date": "2018-05-13T18:51:44.548Z",
"playerOne": "5af888d0b73b2936dcb6dfd3",
"playerOneThrew": "Scissors",
"playerTwo": "5af88918b73b2936dcb6dfd7",
"playerTwoThrew": "Rock",
"winner": "5af88918b73b2936dcb6dfd7",
"__v": 0
}
我希望能够根据玩家ID(可以是playerOne或可以是playerTwo)进行查询,并在每次比赛中都拉回玩家扔出的手牌。从本质上讲,我希望能够通过玩家ID来获得所有游戏的所有掷出的手(石头,纸,剪刀)的总数。
是否可以汇总集合中所有文档的每个“掷手”值的计数并返回类似
的方式{
"player": "5af888d0b73b2936dcb6dfd3",
"Rock": 3,
"Paper": 6,
"Scissors": 12
}
我的想法是根据id匹配playerOne ||来设置一个变量。然后,playerTwo在switch语句中使用该变量,在该语句中汇总“ rock”,“ paper”,“ scissors”的计数。问题是我对使用MongoDB并不陌生,而且我难以理解此类查询的正确语法。
我现在在这里
GameLogs.aggregate(
[
{
$let: {
vars: {
playerThrew: {
$cond: {
if: {
$eq: { playerOne: id },
}
}, then: playerOneThrew, else: playerTwoThrew
}
}
}
},
{
$switch: {
branches: [
{ case: { $eq: 'Rock' }, then: { $count: 'Rock' } },
{ case: { $eq: 'Paper' }, then: { $count: 'Paper' } },
{ case: { $eq: 'Scissors' }, then: { $count: 'Scissors' } },
]
}
}
]
)
伪代码
if playerOne == id
playerThrew = playerOneThrows
else if playerTwo == id
playerThrew = playerTwoThrows
switch playerThrew {
case 'rock':
rockCount++
break
case 'paper':
paperCount++
break
case 'scissors':
scissorsCount++
break
}
return {
player_id: id,
rock: rockCount,
paper: paperCount,
scissors: scissorCount
}
任何见识都会受到赞赏。
答案 0 :(得分:1)
RadosławMiernik的答案很好,但仍然需要$match
,因为OP只想获取特定玩家的数据。
可以说playerId
是需要数据的播放器的_id
。
下面的代码应该起作用,并给出预期的结果
collection.aggregate([
{$project: {
player: [
{id: '$playerOne', threw: '$playerOneThrew'},
{id: '$playerTwo', threw: '$playerTwoThrew'}
],
}},
{$unwind: '$player'},
{$match : {
"player.id" : playerId
}},
{$group: {
_id: '$player.id',
player : {$first : "$player.id},
Paper: {$sum: {$cond: [{$eq: ['$player.threw', 'Paper' ]}, 1, 0]}},
Rock: {$sum: {$cond: [{$eq: ['$player.threw', 'Rock' ]}, 1, 0]}},
Scissors: {$sum: {$cond: [{$eq: ['$player.threw', 'Scissors']}, 1, 0]}}
}}
])
这将提供您正在寻找的确切结果,以及一个额外的_id
字段。
{
"_id": "5af888d0b73b2936dcb6dfd3",
"player": "5af888d0b73b2936dcb6dfd3",
"Rock": 3,
"Paper": 6,
"Scissors": 12
}
答案 1 :(得分:0)
您可以将每个文档分为两个标准化文档,然后轻松将它们分组:
collection.aggregate([
{$match: {
$or: [
{playerOne: playerId},
{playerTwo: playerId}
]
},
{$project: {
player: [
{id: '$playerOne', threw: '$playerOneThrew'},
{id: '$playerTwo', threw: '$playerTwoThrew'}
],
}},
{$unwind: '$player'},
{$match: {'player.id': playerId},
{$group: {
_id: '$player.id',
Paper: {$sum: {$cond: [{$eq: ['$player.threw', 'Paper' ]}, 1, 0]}},
Rock: {$sum: {$cond: [{$eq: ['$player.threw', 'Rock' ]}, 1, 0]}},
Scissors: {$sum: {$cond: [{$eq: ['$player.threw', 'Scissors']}, 1, 0]}}
}}
])
编辑::添加了$match
阶段以仅针对给定玩家有效地过滤分数。