MongoDB: 投影到字段值最小的数组项

MongoDB: Project to array item with minimum value of field

假设我的 collection 包含如下所示的项目:

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

我能否以某种方式 select 具有最低值 item_fielditems 条目,在本例中为 item_id 3 的条目?

我可以使用聚合框架。如果你能给我 C# 驱动程序的代码,加分。

您可以使用 $unwind 来分隔项目条目。 然后$sort by item_field asc and then $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 } }

我们可以使用以下查询得到预期的结果

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 } }

您可以通过以下方式使用$reduce表达式。

下面的查询会将 initialValue 设置为 $items.item_field 的第一个元素,然后在 item_field 上进行 $lt 比较,如果为真则设置 $$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" ] 
                    }
                }
            }
        }
    }
])