MongoDB Как сортировать в обе стороны от числа?

Допустим, в коллекции есть такие документы:

{name: "Test 1", value: "1"}
{name: "Test 2", value: "2"}
{name: "Test 3", value: "3"}
{name: "Test 4", value: "4"}
{name: "Test 5", value: "5"}
{name: "Test 6", value: "6"}

Выбираем медиану значений value ([1,2,3,4,5,6]) - 3.5 Нужно отсортировать документы, чтобы значения шли от медианы (3.5) в обе стороны:

{name: "Test 3", value: "3"}
{name: "Test 4", value: "4"}
{name: "Test 2", value: "2"}
{name: "Test 5", value: "5"}
{name: "Test 1", value: "1"}
{name: "Test 6", value: "6"}

Ответы (1 шт):

Автор решения: Total Pusher

Значение value: "1" не подходит для математических операций, нужно исправить тип со строки на число.

Я буду исходить из того, что данные вставлены по принципу db.data.insert({name: "Test 1", value: 1});.

Итак, нужно сделать вычисляемое поле, по которому отсортировать. Для этого нужно вычесть из value 3.5 и получить абсолютное значение. То есть abs(value - 3.5).

Для этого нужно использовать aggregate, в котором добавить project, где с помощью функций вычислить значение:

db.data.aggregate([
    {
        $project: {
            "_id": 0,
            "name": 1,
            "value": 1,
            "orderBy": {
                $abs: {
                    $add: ["$value", -3.5]
                }
            }
        }
    },
    {"$sort": {"orderBy": 1}}
]);

Результат:

{ "name" : "Test 3", "value" : 3, "orderBy" : 0.5 }
{ "name" : "Test 4", "value" : 4, "orderBy" : 0.5 }
{ "name" : "Test 2", "value" : 2, "orderBy" : 1.5 }
{ "name" : "Test 5", "value" : 5, "orderBy" : 1.5 }
{ "name" : "Test 1", "value" : 1, "orderBy" : 2.5 }
{ "name" : "Test 6", "value" : 6, "orderBy" : 2.5 }

Еще раз повторю, что value должно быть числом, а не строкой, иначе будет ошибка. Либо нужно сделать преобразование типов через $toInt, но эта операция доступна в Mongo 4+, и я не могу проверить. Но должно быть так:

"orderBy": {
    $abs: {
        $add: [
            {$toInt: "$value"}, -3.5
        ]
    }
}
→ Ссылка