Mon go Агрегирование БД, объединяющее несколько значений, принадлежащих одному и тому же документу - PullRequest
0 голосов
/ 01 февраля 2020

У меня есть документы, которые выглядят следующим образом

{
"_id": "5e3334cede31d9555e38dbee",
"time": 400,
"datetime": "2020-01-05T16:35:42.315Z",
"version": "2.0.30",
"hostname": "bvasilchik-lt.extron.com",
"testfile": "cards.txt",
"tests": 5,
"failures": 3,
"skips": 0,
"status": "Failed",
"__v": 0
}

Я хочу создать результат, включающий документы, которые имеют наибольшее количество времени на имя тестового файла, поэтому, если первые 10 были одинаковыми testfile name Я бы хотел показать только топ с тем же именем тестового файла.

Я сделал это, но я также хотел включить другое поле, которое также показывает количество тестов, соответствующих этой группе, но я нашел только один способ - добавить $ first или $ last или $ max или $ min для поля тестов, но это не будет правильно b / c наибольшее время может иметь разное количество тестов.

Я также сопоставляю результаты из указанного диапазона дат c

const times = await Suite.aggregate([
    {
        "$match": {
            datetime: { "$gte": dateRange.startDate, "$lt": dateRange.endDate, }
        }
    },
    {
        "$group": {
            _id: "$testfile",
            time: { "$max" : "$time" },
        }
    },
    {
        "$sort": {
            time: order
        }
    },
    {
        "$project": {
            _id: 0,
            testfile: "$_id",
            time: "$time"
        }
    }
])

это приводит к этим результатам

[
    {
    "testfile": "lists.txt",
    "time": 900
    },
    {
    "testfile": "buttons.txt",
    "time": 800
    },
    {
    "testfile": "cards.txt",
    "time": 400
    },
    {
    "testfile": "popover.txt",
    "time": 300
    },
    {
    "testfile": "about-pages.neb",
    "time": 76
    }
]

, но я хочу, чтобы это было возвращено

[
    {
    "testfile": "lists.txt",
    "tests": 5, 
    "time": 900
    },
    {
    "testfile": "buttons.txt",
    "tests": 4,
    "time": 800
    },
    {
    "testfile": "cards.txt",
    "tests": 8,
    "time": 400
    },
    {
    "testfile": "popover.txt",
    "tests": 1,
    "time": 300
    },
    {
    "testfile": "about-pages.neb",
    "tests": 2,
    "time": 76
    }
]

1 Ответ

1 голос
/ 01 февраля 2020

Вам необходимо добавить дополнительное поле в $group и $project этапы.

Вам необходимо использовать оператор $max для поля time и накапливать tests поле time:tests значений. На последнем этапе у нас $reduce tests поле принимает наибольшее значение

{
  "$group": {
    _id: "$testfile",
    time: {
      $max: "$time"
    },
    tests: {
      "$push": {
        time: "$time",
        tests: "$tests"
      }
    }
  }
},
{
  "$sort": {
    time: 1
  }
},
{
  "$project": {
    _id: 0,
    testfile: "$_id",
    time: "$time",
    tests: {
      $reduce: {
        input: "$tests",
        initialValue: 0,
        in: {
          $add: [
            "$$value",
            {
              $cond: [
                {
                  $and: [
                    {
                      $eq: [
                        "$time",
                        "$$this.time"
                      ]
                    },
                    {
                      $gt: [
                        "$$this.tests",
                        "$$value"
                      ]
                    }
                  ]
                },
                {
                  $subtract: [
                    "$$this.tests",
                    "$$value"
                  ]
                },
                0
              ]
            }
          ]
        }
      }
    }
  }
}

MongoPlayground

...