Совокупное количество различных полей в документе на основе условия - PullRequest
0 голосов
/ 30 июня 2018

Я надеюсь получить определенные значения и подсчитать, сколько раз эти значения находятся в коллекции, основываясь на том, какой ключ имеет определенный идентификатор. Например, вот пример одного документа из коллекции игровых журналов

{
    "_id": "5af88940b73b2936dcb6dfdb",
    "date": "2018-05-13T18:51:44.548Z",
    "playerOne": "5af888d0b73b2936dcb6dfd3",
    "playerOneThrew": "Scissors",
    "playerTwo": "5af88918b73b2936dcb6dfd7",
    "playerTwoThrew": "Rock",
    "winner": "5af88918b73b2936dcb6dfd7",
     "__v": 0
}

Я рассчитываю на возможность запроса на основе идентификатора игрока (может быть playerOne или playerTwo) и вытягивает руку, которую игрок бросал для каждого матча. По сути, я хочу получить общее количество всех брошенных рук (камень, бумага, ножницы) во всех играх по идентификатору игрока.

Есть ли способ объединить счетчик для каждого значения "брошенной руки" для всех документов в коллекции и вернуть что-то вроде

{
    "player": "5af888d0b73b2936dcb6dfd3",
    "Rock": 3,
    "Paper": 6,
    "Scissors": 12
}

Мои мысли - установить переменную, в зависимости от того, какой идентификатор соответствует 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' } },
        ]
      }
    }
  ]
)

Psuedocode

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
}

Любое понимание будет оценено.

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Ответ Радослава Мирника хороший, но все равно требуется $match, так как ОП хочет получать данные только для конкретного игрока.

Допустим, 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
}
0 голосов
/ 30 июня 2018

Вы можете разделить каждый из ваших документов на два нормализованных и затем сгруппировать их легко:

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 этапов для эффективной фильтрации результатов только для данного игрока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...