根据另一个嵌入文档的搜索条件获取嵌入文档

fetching embedded documents on search criteria of another embedded document

我有一个 HostelTbl 集合,里面有很多文档,其中一个文档是这样的

    {
    "_id": ObjectId("5ae69fb4d2ccda0e70005551"),
    "Name": "Hostel-MGL-02",
     ...
    "RoomsDetails": [
     {
       "RoomId": "9a21e427-16fd-7a9e-bc16-537dc55093bb",
       "FloorNumber": "1",
       "RoomNumber": "101",
        ...
     },
     {
       "RoomId": "050c65ab-355e-9bec-00a0-2999e75bcdc4",
       "FloorNumber": "1",
       "RoomNumber": "104",
       ...
     },
     {
       "RoomId": "f197c635-a6fb-b4d6-9cf5-ed53177edd47",
       "FloorNumber": "2",
       "RoomNumber": "109",
       ...
     },
     ...
     {
       ...
     }
    ],
   "AllotmentsDetails": [
   {
      "AllotmentId": "5eb05e1d-2690-afad-747a-ef29450ae3f3",
      "StudentId": ObjectId("5ab8d5d4ff24ae120400085e"),
      "RoomId": "9a21e427-16fd-7a9e-bc16-537dc55093bb",
      "FromDate": ISODate("2018-06-12T22:00:00.0Z"),
      "ToDate": ISODate("2018-07-04T22:00:00.0Z"),
      ... 
     },
     {
      "AllotmentId": "40d73d84-0f94-48d8-823c-2255fd2ae0ed",
      "StudentId": ObjectId("5ab8d5bcff24ae120400085d"),
      "RoomId": "050c65ab-355e-9bec-00a0-2999e75bcdc4",
      "FromDate": ISODate("2018-01-21T22:00:00.0Z"),
      "ToDate": ISODate("2018-02-06T22:00:00.0Z"),
      ...
       },
       {
      "AllotmentId": "40d73564-0f94-48d8-823c-2255fd2440428",
      "StudentId": ObjectId("5ab8d5bc4624ae1204000855),
      "RoomId": "f197c635-a6fb-b4d6-9cf5-ed53177edd47",
      "FromDate": ISODate("2018-03-21T22:00:00.0Z"),
      "ToDate": ISODate("2018-05-04T22:00:00.0Z"),
      ...
       } 
     ] 
  }

我在一个文档中嵌入了两个文档。一个存储房间信息,另一个存储分配给学生的房间信息。 现在我想从 RoomsDetails 获取那些可用房间,如果他们的分配详细信息的 "ToDate" 字段包含 AllotmentsDetails 嵌入式文档中从今天开始的过去日期。就像在上面的例子中,带有 id 的房间 “050c65ab-355e-9bec-00a0-2999e75bcdc4”,f197c635-a6fb-b4d6-9cf5-ed53177edd47 包含过去在 AllotmentsDetails 嵌入文档中的 ToDate 日期。它应该只获取那两个房间。

我找不到这样的查询。请帮忙!!!

我正在尝试调整以下代码行

public function fetchAllAvailableRooms() 
{
   $cursor = $this->collection->aggregate(array(
             array(
                   '$match' => array(
                                "_id" => new MongoDB\BSON\ObjectID($this->id)
                                )
                  ),
             array(
                  '$project' => array(
                  'RoomsDetails' => array(
                  '$filter' => array(
                  'input' => '$AllotmentsDetails',
                  'as' => 'allot',
                  'cond' => array(
                  '$lt' => array('$$allot.FromDate', $this->Today)
                   )
                  )
                 ),
               'Name' => 1        
                )
              )
            ))->toArray();

    return $cursor;
   } 

您可以为此使用 $map and $filter 聚合运算符。

  • $map - 用于 AllotmentsDetails 转换为最终列表 房间 ID

  • $filter - RoomsDetails 过滤 房间 ID 的最终列表

示例:

public function fetchAllAvailableRooms() 
{
    $cursor = $this->collection->aggregate([
        ['$match' => ["_id" => new MongoDB\BSON\ObjectID($this->id)]],
        [
            '$addFields' => [
                'filteredIds' => [
                    '$map' => [
                        'input' => '$AllotmentsDetails',
                        'as' => 'item',
                        'in' => [
                            '$cond' => [
                                ['$lt' => ['$$item.ToDate', $this->Today]],
                                '$$item.RoomId',
                                false
                            ]
                        ]
                    ]
                ]
            ]
        ],
        [
            '$project' => [
                'RoomsDetails' => [
                    '$filter' => [
                        'input' => '$RoomsDetails',
                        'as' => 'item',
                        'cond' => ['$in' => ['$$item.RoomId', '$filteredIds']]
                    ]
                ]
            ]
        ]
    ])->toArray();

    return $cursor;
} 

/* Result example
{
    "_id" : ObjectId("5ae69fb4d2ccda0e70005551"),
    "RoomsDetails" : [ 
        {
            "RoomId" : "050c65ab-355e-9bec-00a0-2999e75bcdc4",
            "FloorNumber" : "1",
            "RoomNumber" : "104"
        }, 
        {
            "RoomId" : "f197c635-a6fb-b4d6-9cf5-ed53177edd47",
            "FloorNumber" : "2",
            "RoomNumber" : "109"
        }
    ]
}
*/

P.S。 PHP 代码未经测试,所以我不能 100% 确定它是否有效。

P.P.S。最终的解决方案在很大程度上取决于您的项目的细节。