如何正确制作多个字段 $min

How to make multiple fields $min properly

我有以下合集:

{
  TariffId: 0101H01,
  RoomId: 01H01,
  HotelId: H01,
  Price: 180,
  ...       //other fields
},
{
  TariffId: 0201H01,
  RoomId: 01H01,
  HotelId: H01,
  Price: 120
}
{ 
  TariffId: 0301H01,
  RoomId: 02H01,
  HotelId: H01,
  Price: 100
  ...       //other fields
}

我想输出每个 HotelId 的最低价格,并确切知道它与哪个 RoomId 和 TariffId 以及所有其他字段相关。结果应该是:

{ 
  TariffId: 0201H01,
  RoomId: 01H01,
  HotelId: H01,
  Price: 120
}
{ 
  TariffId: 0301H01,
  RoomId: 02H01,
  HotelId: H01,
  Price: 100
  ...       //other fields
}

我试过:

 db.collection.aggregate{
      {$group: {_id :{ RoomId: "$RoomId", tariffId: "$_id"} , HotelId:{$first: "$HotelId"} , Price: {$min: "$Price" }}},
      {$group: {_id : "$HotelId", RoomId: {$first:"$RoomId"}, tariffId: {$first: "$_id"} , Price: {$min: "$Price" }}}
      } 

但是结果不正确。第一个错误地将 tariffIdm0101H01 分配给最低价格:120。这是我得到的:

{ 
  TariffId: 0101H01,
  RoomId: 01H01,
  HotelId: H01,
  Price: 100
  ...       //other fields
}

应该是:

{ 
  TariffId: 0301H01,
  RoomId: 02H01,
  HotelId: H01,
  Price: 100
  ...       //other fields
}

如何使这个查询有效?

问题

您得到错误价格的原因是您使用了两个独立的运算符($min$first)并且它们彼此不同步。 $min 正在返回整个集合中的最低价格,$first 正在从整个集合中获取第一个文档。

解决方案

你要做的是排序(确保有一个索引),然后分组并使用 $first 运算符。由于我们在分组之前进行排序,第一个文档将是价格最低的文档。

db.collection.aggregate([
    // important sort by price before grouping
    {
        $sort: { Price: 1 }
    },
    // group by hotel and room ID and get the first document
    {
        $group: {
            _id: {                
                HotelId: '$HotelId',
                RoomId: "$RoomId",
            },
            doc: { $first: '$$ROOT' }
        }
    },
    // (optional) replace the root document
    {
        $replaceRoot: { newRoot: '$doc' }
    }
])