Подтвердить что ты не робот

Mongodb: сортировка документов по массивам

Я хотел бы вернуть документы в порядке, упорядоченном по которому выполняется самое низкое значение foo.bar (которое является объектами массива).

Я могу сделать db.collection.find().sort({foo.0.bar: 1}), но это соответствует только первому элементу массива - и, как вы можете видеть в приведенном ниже примере, сначала будет сортировать элемент 1 (foo.0.bar = 5), если я ищу return item 2 first (foo.2.bar = 4), поскольку он имеет объект с наименьшим значением.

{
    "name": "Item 1",
    "foo": [
        {
            "bar": 5
        },
        {
            "bar": 6
        },
        {
            "bar": 7
        }
    ]
}
{
    "name": "item 2",
    "foo": [
        {
            "bar": 6
        },
        {
            "bar": 5
        },
        {
            "bar": 4
        }
    ]
}
4b9b3361

Ответ 1

Кажется, монго может это сделать.

Например, если у меня есть следующие документы:

{ a:{ b:[ {c:1}, {c:5 } ] } }
{ a:{ b:[ {c:0}, {c:12} ] } }
{ a:{ b:[ {c:4}, {c:3 } ] } }
{ a:{ b:[ {c:1}, {c:9 } ] } }

И запустите следующее:

db.collection.find({}).sort({ "a.b.c":1 });
// produces:
{ a:{ b:[ {c:0}, {c:12} ] } }
{ a:{ b:[ {c:1}, {c:5 } ] } }
{ a:{ b:[ {c:1}, {c:9 } ] } }
{ a:{ b:[ {c:4}, {c:3 } ] } }

db.collection.find({}).sort({ "a.b.c":-1 });
// produces:
{ a:{ b:[ {c:0}, {c:12} ] } }
{ a:{ b:[ {c:1}, {c:9 } ] } }
{ a:{ b:[ {c:1}, {c:5 } ] } }
{ a:{ b:[ {c:4}, {c:3 } ] } }

Как вы можете видеть, сортировка {"a.b.c":1} принимает min всех значений в массиве и сортирует по ней, тогда как сортировка по {"a.b.c":-1} занимает max всех значений.

Ответ 2

Альтернативой использованию map/reduce является сохранение значения min из массива в виде отдельного поля в документе, который вы могли бы затем заказать. Когда вы добавляете в массив, вы также обновляете это поле, если новое значение меньше, чем текущий записанный минимум.

например. ваш первый документ станет таким (примечание "добавлено minbar" ):

{
    "name": "Item 1",
    "minbar" : 5,
    "foo": [
        {
            "bar": 5,
        }
        {
            "bar": 6,
        }
        {
            "bar": 7,
        }
    ]
}

Ответ 3

Вы можете сделать такой вид с помощью агрегатной команды из версии mongo 2.2:

    db.collection.aggregate([{$unwind: "$foo"},
    {$project: {bars:"$foo.bar"}},
    {$group: {_id:"$_id",min:{$min: "$bars"}}},
    {$sort: {min:1}}])

Ответ 4

Нет прямого способа сделать это в монго. Вам нужно будет использовать map/reduce для извлечения min val в каждом массиве, а затем сортировать по этому минимальному значению