在另一个嵌入文档的搜索条件上获取嵌入文档

时间:2018-06-04 07:18:48

标签: mongodb mongodb-query aggregation-framework mongodb-php php-mongodb

我有一个集合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嵌入式文档中的日期。就像在上面的情况下房间有ids " 050c65ab-355e-9bec-00a0-2999e75bcdc4",f197c635-a6fb-b4d6-9cf5-ed53177edd47包含过去在AllotmentsDetails嵌入文档中的日期。它应该只取这两个房间。

我无法找到此类查询。请帮忙!!!

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

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

1 个答案:

答案 0 :(得分:1)

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

  • $map - 将AllotmentsDetails转换为最终列表 房间ids

  • $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。最终的解决方案很大程度上取决于项目的细节。