Агрегация MongoDB - как получить процентное значение по ставке - PullRequest
1 голос
/ 15 февраля 2020

Я пытаюсь получить информацию о базе данных всех сборов данных

мои данные:

{
    _id : 1,
    age : 21,
    salary : 2500
},
{
    _id : 2,
    age : 42,
    salary : 4300
},
{
    _id : 3,
    age : 32,
    salary : 3100
},
{
    _id : 4,
    age : 18,
    salary : 7000
},
{
    _id : 5,
    age : 25,
    salary : 5600
},
{
    _id : 6,
    age : 28,
    salary : 5200
}
,
{
    _id : 7,
    age : 38,
    salary : 5000
},
{
    _id : 8,
    age : 28,
    salary : 5200
}

Я хочу разделить значения на четыре варианта.

Первый вариант - 25 процентов.

Значения второй опции от 25 до 50 процентов.

Третий вариант от 50 до 75 процентов и

последняя опция от 75 до 100 процентов.

Поэтому, когда я хочу вытащить объект, он покажет мне значения относительно других значений.

например:

{
    _id : 4,
    age : 'less than 25 percent',
    salary : 'more than 75 percent'
}

Ответы [ 2 ]

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

Вы можете сделать это, используя $ bucketAuto , который по умолчанию разбил бы все документы коллекции на заданные, по всей вероятности, равные номера корзин

Шаги:

  1. Используйте $ facet , чтобы создать один массив для age и один для salary, каждый массив 4 вложенных документа со всеми документами, разделенными поровну на 4 сегмента документы). Добавляет каждый сопоставленный документ в массив data.
  2. Размотайте age & salary, чтобы получить объекты вместе с их указанными c индексами.
  3. Используйте $ addFields для замены существующих полей age & salary текстами, соответствующими их позициям в сегментах.
  4. Используйте $ project & $ concatArrays для объединения двух массивов в один массив с именем data.
  5. размотка data массив & $ group на _id добавление уникальных текстов в age & salary.
  6. age & salary являются массивом отдельных элементов (строк), поэтому с помощью $ arrayElemAt получаем первый элемент, чтобы сделать age & salary как поля с типом string.

Запрос:

db.collection.aggregate([
    {
        $facet: {
            "age": [
                {
                    $bucketAuto: {
                        groupBy: "$age",
                        buckets: 4,
                        output: {
                            "data": { $push: { '_id': "$$ROOT._id", age: "$$ROOT.age" } }
                        }
                    }
                }
            ],
            "salary": [
                {
                    $bucketAuto: {
                        groupBy: "$salary",
                        buckets: 4,
                        output: {
                            "data": { $push: { '_id': "$$ROOT._id", salary: "$$ROOT.salary" } }
                        }
                    }
                }
            ]
        }
    }, { $unwind: { path: '$age', includeArrayIndex: "arrayIndexAge" } },
       { $unwind: { path: '$salary', includeArrayIndex: "arrayIndexSalary" } },
    {
        $addFields: {
            'age.data.age': {
                $switch: {
                    branches: [
                        { case: { $eq: ['$arrayIndexAge', 0] }, then: "less than 25 percent" },
                        { case: { $eq: ['$arrayIndexAge', 1] }, then: "​​between 25 and 50 percent" },
                        { case: { $eq: ['$arrayIndexAge', 2] }, then: "between 50 and 75 percent" },
                        { case: { $eq: ['$arrayIndexAge', 3] }, then: "more than 75 percent" }
                    ]
                }
            },
            'salary.data.salary': {
                $switch: {
                    branches: [
                        { case: { $eq: ['$arrayIndexSalary', 0] }, then: "less than 25 percent" },
                        { case: { $eq: ['$arrayIndexSalary', 1] }, then: "​​between 25 and 50 percent" },
                        { case: { $eq: ['$arrayIndexSalary', 2] }, then: "between 50 and 75 percent" },
                        { case: { $eq: ['$arrayIndexSalary', 3] }, then: "more than 75 percent" }
                    ]
                }
            }
        }
    }, { $project: { data: { $concatArrays: ['$age.data', '$salary.data'] } } }, { $unwind: '$data' },
    { $group: { _id: '$data._id', age: { $addToSet: '$data.age' }, salary: { $addToSet: '$data.salary' } } },
    { $addFields: { age: { $arrayElemAt: ['$age', 0] }, salary: { $arrayElemAt: ['$salary', 0] } } }])

Тест: MongoDB-Playground

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

Посмотрите, соответствует ли это вашим требованиям.

Пояснение

Агрегирование Mongodb предлагает больше аналитических операций для вычисления данных. С помощью операции $facet мы можем вычислить несколько агрегаций в одном.

Мы вычисляем минимальные / максимальные значения для salary и age. Затем мы вычисляем процент для каждого salary и age с помощью этой формулы

 x  − min
---------- x 100
max − min

С помощью $switch мы определяем 4 варианта: менее 25, меньше 50, меньше 75 и больше хан 75


db.collection.aggregate([
  {
    $facet: {
      extremes: [
        {
          $group: {
            _id: null,
            maxAge: {
              $max: "$age"
            },
            minAge: {
              $min: "$age"
            },
            maxSalary: {
              $max: "$salary"
            },
            minSalary: {
              $min: "$salary"
            }
          }
        }
      ],
      root: [
        {
          $match: {}
        }
      ]
    }
  },
  {
    $set: {
      extremes: {
        $arrayElemAt: [
          "$extremes",
          0
        ]
      }
    }
  },
  {
    $unwind: "$root"
  },
  {
    $addFields: {
      root: {
        agePercent: {
          $toInt: {
            $multiply: [
              {
                $divide: [
                  {
                    $subtract: [
                      "$root.age",
                      "$extremes.minAge"
                    ]
                  },
                  {
                    $subtract: [
                      "$extremes.maxAge",
                      "$extremes.minAge"
                    ]
                  }
                ]
              },
              100
            ]
          }
        },
        salaryPercent: {
          $toInt: {
            $multiply: [
              {
                $divide: [
                  {
                    $subtract: [
                      "$root.salary",
                      "$extremes.minSalary"
                    ]
                  },
                  {
                    $subtract: [
                      "$extremes.maxSalary",
                      "$extremes.minSalary"
                    ]
                  }
                ]
              },
              100
            ]
          }
        }
      }
    }
  },
  {
    $replaceWith: "$root"
  },
  {
    $project: {
      age: {
        $switch: {
          branches: [
            {
              case: {$lt: ["$agePercent",25]},
              then: "less than 25 percent"
            },
            {
              case: {$lt: ["$agePercent",50]},
              then: "less than 50 percent"
            },
            {
              case: {$lt: ["$agePercent",75]},
              then: "less than 75 percent"
            },
            {
              case: {$gte: ["$agePercent",75]},
              then: "more than 75 percent"
            }
          ],
          default: "Unknown"
        }
      },
      salary: {
        $switch: {
          branches: [
            {
              case: {$lt: ["$salaryPercent",25]},
              then: "less than 25 percent"
            },
            {
              case: {$lt: ["$salaryPercent",50]},
              then: "less than 50 percent"
            },
            {
              case: {$lt: ["$salaryPercent",75]},
              then: "less than 75 percent"
            },
            {
              case: {$gte: ["$salaryPercent",75]},
              then: "more than 75 percent"
            }
          ],
          default: "Unknown"
        }
      }
    }
  }
])

MongoPlayground

...