MongoDB рассчитывать по истине в совокупной группе - PullRequest
0 голосов
/ 11 марта 2019

Я пытаюсь простым способом усреднить и суммировать некоторые статистические данные, но попал в стену!

У меня есть коллекция документов с некоторой статистикой, подобной этой:

{
  "playerId": "5c6024b5031f5bc44d790e01",
  "courseId": "5b2a0ab1c6dc0f04e9a1e769",
  "gir": true,
  "data": {
    "roundHoles": [
      {
        "type": "HoleData",
        "holeNo": 1,
        "par": 3,
        "hcp": 18
      },
      {
        "type": "HoleData",
        "holeNo": 2,
        "par": 4,
        "hcp": 4
      },
      {
        "type": "HoleData",
        "holeNo": 3,
        "par": 4,
        "hcp": 8
      }
    ],
    "holeScores": [
      {
        "type": "RoundHoleData",
        "strokes": 3,
        "points": 2,
        "puts": 1,
        "gir": true,
        "scrambled": false
      },
      {
        "type": "RoundHoleData",
        "strokes": 5,
        "points": 1,
        "puts": 2,
        "gir": false,
        "scrambled": false
      },
      {
        "type": "RoundHoleData",
        "strokes": 4,
        "points": 2,
        "puts": 1,
        "gir": false,
        "scrambled": true
      }
    }
  }
}

То, что я хотел бы сделать, это получить средние удары, точки и путы, а также сумму схваток и gir, когда true, но только если основной «gir» установлен в true.

Вот что я придумал до сих пор:

var allScores = runtimeCollection('roundScores').aggregate(
  {
      $match: { "playerId": playerId, "courseId": "5b2a0ab1c6dc0f04e9a1e769" }
  },
  {
      $unwind: {
          path: "$data.holeScores",
          includeArrayIndex: "index"
      }
  },
  {
      $group: {
          _id: "$index",
          rounds: { $sum: 1 },
          avgStrokes: { $avg: "$data.holeScores.strokes" },
          avgPoints: { $avg: "$data.holeScores.points" },
          avgPuts: { $avg: "$data.holeScores.puts" },
          sumScrambles: { $sum: "$data.holeScores.scrambled" }
      }
  }
);

Вот что я получил от этого:

{
  "_id": 17,
  "rounds": 18,
  "avgStrokes": 3.4444444444444446,
  "avgPoints": 1.2777777777777777,
  "avgPuts": 1.6111111111111112,
  "sumScrambles": 0
},
{
  "_id": 14,
  "rounds": 18,
  "avgStrokes": 5.388888888888889,
  "avgPoints": 2.1666666666666665,
  "avgPuts": 1.5,
  "sumScrambles": 0
},
{
  "_id": 12,
  "rounds": 18,
  "avgStrokes": 5,
  "avgPoints": 1.6111111111111112,
  "avgPuts": 1.8333333333333333,
  "sumScrambles": 0
}

Похоже, я получаю средние части просто отлично, но сумма не работает. Я думаю, что я должен добавить условие к sumScrambles, но не уверен, как?

Действительно надеюсь, что кто-то может помочь мне с этим, и спасибо заранее: -)

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Вам не обязательно нужно $unwind и $group, чтобы получить средние значения и сумму для этого агрегата, все можно сделать в $project этап поскольку операторы $sum и $avg также работают на этапе $project, если поля являются массивами.

Что касается условных сумм, вы можете использовать $filter в массиве, а затем подсчитать элементы в сокращенном массиве с помощью $size, чтобы получить сумму.

Следующий конвейер демонстрирует этот подход

runtimeCollection('roundScores').aggregate([
    { '$match': { 'playerId': playerId, 'courseId': '5b2a0ab1c6dc0f04e9a1e769' } },
    { '$project': {
        'rounds': { '$size': '$data.holeScores' },
        'avgStrokes': { '$avg': '$data.holeScores.strokes' },
        'avgPoints': { '$avg': '$data.holeScores.points' },
        'avgPuts': { '$avg': '$data.holeScores.puts' },
        'avgPars': { '$avg': '$data.roundHoles.par' },
        'sumScrambles': { 
            '$size': {
                '$filter': {
                    'input': '$data.holeScores',
                    'cond': '$$this.scrambled'
                }
            }
        }
    } }
])
1 голос
/ 11 марта 2019

Хорошо, во-первых, вы не можете получить сумму логических значений, вы можете получить только сумму чисел.Итак, я предполагаю, что вы хотите добавить 1 всякий раз, когда зашифрованное значение истинно, в этом случае вы можете использовать ' $ cond ', который позволяет вам писать условия.

Выможно попробовать что-то вроде этого,

sumScrambles: { $sum: { $cond: [ { $eq: [ "$data.holeScores.scrambled", true ] }, 1, 0 ] } }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...