MongoDB compass - получить имя поля (ключ) с максимальным значением из 3 полей и их значений в документе - PullRequest
2 голосов
/ 29 октября 2019

У меня есть этот образец документа mongodb -

{
    _id: 5db85ee97d9fb13ead4fc54c
    applId: 5d48f34f7d9fb10ce171f905
    fileId: "dd386cf7-4139-45c2-9853-cbb126621b51"
    job: Object
    country: "US"
    fullName: "abcd xyz"
    htmlWordCount: 2766
    textWordCount: 1867
    rchilliTextWordCount: 2840
    deleted: 0
    dateEntered: 2019-10-29 15:46:49.237
    dateModified: 2019-10-29 15:46:49.237
}

Я хочу построить запрос в компасе, чтобы у меня были следующие поля в выводе -

{
    _id: 5db85ee97d9fb13ead4fc54c
    country: "US"
    fullName: "abcd xyz"
    htmlWordCount: 2766
    textWordCount: 1867
    rchilliTextWordCount: 2840
    winner: "rchilliTextWordCount"
}

Обратите внимание, что этоимеет новое поле с именем "winner", которое всегда возвращает столбец с максимальным количеством слов (из 3 "htmlWordCount", "textWordCount", "rchilliTextWordCount" столбцов). Этот новый столбец "winner" должен создаваться во время выполнения по запросу. Также этот запрос фильтруется по country = "US".

Как мне это сделать в MongoDB Compass или как должен выглядеть конвейер агрегации?

Ответы [ 2 ]

2 голосов
/ 30 октября 2019

Это еще один подход к получению результата:

  1. Получить имена полей документа и их значения
  2. Найти максимальное значение для полей с именами в [ "htmlWordCount", "textWordCount", "rchilliTextWordCount" ].

Как правило, поиск максимального значения из массива является своего рода сокращением ;поэтому я использовал $reduce в этом случае. Обратите внимание, что код проще. Если вы хотите добавить другое поле для расчета максимума, просто добавьте его в массив.

db.winner.aggregate([
  { $match: { country: "US"} },
  { $addFields: { fieldNameValues: { "$objectToArray": "$$ROOT" } } },
  { $project: { _id: 1, country: 1, fullName: 1, htmlWordCount: 1, textWordCount: 1, rchilliTextWordCount: 1, 
                winner: { 
                    $reduce: {
                        input: "$fieldNameValues",
                        initialValue: { },
                        in: {
                            $cond: [
                               { $and: [ 
                                   { $in: [ "$$this.k", [ "htmlWordCount", "textWordCount", "rchilliTextWordCount" ] ] }, 
                                   { $gt: [ "$$this.v", "$$value.v"] } ]
                               },
                               "$$this",
                               "$$value"
                            ]
                        }
                    } 
               } 
  } },
  { $addFields: { winner: "$winner.k" } }
] )



[EDIT ADD]

Пример данных и результат:

{
        "_id" : 1,
        "fileId" : "dd386cf7-4139-45c2-9853-cbb126621b51",
        "job" : { },
        "country" : "US",
        "fullName" : "abcd xyz",
        "htmlWordCount" : 2766,
        "textWordCount" : 1867,
        "rchilliTextWordCount" : 2840
}
{
        "_id" : 2,
        "fileId" : "dd386cf7-4139-45c2-9853-cbb126621b51",
        "job" : { },
        "country" : "US",
        "fullName" : "lmn opqrs",
        "htmlWordCount" : 5,
        "textWordCount" : 9,
        "rchilliTextWordCount" : 2
}

Выход:

{
        "_id" : 1,
        "country" : "US",
        "fullName" : "abcd xyz",
        "htmlWordCount" : 2766,
        "textWordCount" : 1867,
        "rchilliTextWordCount" : 2840,
        "winner" : "rchilliTextWordCount"
}
{
        "_id" : 2,
        "country" : "US",
        "fullName" : "lmn opqrs",
        "htmlWordCount" : 5,
        "textWordCount" : 9,
        "rchilliTextWordCount" : 2,
        "winner" : "textWordCount"
}
2 голосов
/ 30 октября 2019

Вы можете использовать $ switch или $ cond

db.collection.aggregate([
  {
    $match: {
      country: "US"
    }
  },
  {
    $project: {
      country: 1,
      fullName: 1,
      htmlWordCount: 1,
      textWordCount: 1,
      rchilliTextWordCount: 1,
      winner: {
        $switch: {
          branches: [
            {
              case: {
                $and: [
                  {
                    $gt: [
                      "$htmlWordCount",
                      "$textWordCount"
                    ]
                  },
                  {
                    $gt: [
                      "$htmlWordCount",
                      "$rchilliTextWordCount"
                    ]
                  }
                ]
              },
              then: "htmlWordCount"
            },
            {
              case: {
                $and: [
                  {
                    $gt: [
                      "$textWordCount",
                      "$htmlWordCount"
                    ]
                  },
                  {
                    $gt: [
                      "$textWordCount",
                      "$rchilliTextWordCount"
                    ]
                  }
                ]
              },
              then: "textWordCount"
            },
            {
              case: {
                $and: [
                  {
                    $gt: [
                      "$rchilliTextWordCount",
                      "$htmlWordCount"
                    ]
                  },
                  {
                    $gt: [
                      "$rchilliTextWordCount",
                      "$textWordCount"
                    ]
                  }
                ]
              },
              then: "rchilliTextWordCount"
            }
          ],
          default: "No winners"
        }
      }
    }
  }
])

MongoPlayground

...