MongoDB: Проект для массива элемента с минимальным значением поля

Предположим, моя коллекция состоит из элементов, которые выглядят так:

{
    "items" : [
        {
            "item_id": 1,
            "item_field": 10
        },
        {
            "item_id": 2,
            "item_field": 15
        },
        {
            "item_id": 3,
            "item_field": 3
        },
    ]
}

Могу ли я как-то выбрать запись items с самым низким значением item_fieldв этом случае тот, с item_id 3?

Я в порядке с использованием структуры агрегации. Бонус, если вы можете дать мне код для драйвера C#.

3 ответа

Решение

Ты можешь использовать $reduce Выражение следующим образом.

Приведенный ниже запрос установит initialValue к первому элементу $items.item_field и затем $lt сравнение на item_field и если истина установлена $$this в $$value, если false, сохраните предыдущее значение и $reduce все значения, чтобы найти минимальный элемент и $project для вывода минимального элемента.

db.collection.aggregate([
    {
         $project:  {
            items: {
                $reduce: {
                    input: "$items",
                    initialValue:{ 
                         item_field:{ 
                            $let: { 
                                vars: { obj: { $arrayElemAt: ["$items", 0] } },
                                in: "$$obj.item_field"
                            }
                        }
                    },
                    in: {
                          $cond: [{ $lt: ["$$this.item_field", "$$value.item_field"] }, "$$this", "$$value" ] 
                    }
                }
            }
        }
    }
])

Мы можем получить ожидаемый результат, используя следующий запрос

db.testing.aggregate([{$unwind:"$items"}, {$sort: { 'items.item_field': 1}},{$group: {_id: "$_id", minItem: {$first: '$items'}}}])

Результат

{ "_id" : ObjectId("58edf28c73fed29f4b741731"), "minItem" : { "item_id" : 3, "item_field" : 3 } }
{ "_id" : ObjectId("58edec3373fed29f4b741730"), "minItem" : { "item_id" : 3, "item_field" : 3 } }

Вы можете использовать $unwind для разделения записей элементов. Затем $sort по item_field asc, а затем $ group.

db.coll.find().pretty()
{
    "_id" : ObjectId("58edec875748bae2cc391722"),
    "items" : [
        {
            "item_id" : 1,
            "item_field" : 10
        },
        {
            "item_id" : 2,
            "item_field" : 15
        },
        {
            "item_id" : 3,
            "item_field" : 3
        }
    ]
}

db.coll.aggregate([
  {$unwind: {path: '$items', includeArrayIndex: 'index'}}, 
  {$sort: { 'items.item_field': 1}},
  {$group: {_id: '$_id', item: {$first: '$items'}}} 
])
{ "_id" : ObjectId("58edec875748bae2cc391722"), "item" : { "item_id" : 3, "item_field" : 3 } }
Другие вопросы по тегам