извлечение встроенных документов по критериям поиска другого внедренного документа - PullRequest
0 голосов
/ 04 июня 2018

У меня есть коллекция 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.Как и в приведенном выше случае, номера с идентификаторами "050c65ab-355e-9bec-00a0-2999e75bcdc4", f197c635-a6fb-b4d6-9cf5-ed53177edd47 содержит даты ToDate в прошлом во вложенных документах 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 голосов
/ 04 июня 2018

Для этого можно использовать операторы агрегирования $map и $filter.

  • $map - для преобразования AllotmentsDetails в окончательный список идентификаторов номеров

  • $filter - для фильтрации RoomsDetails по окончательному списку идентификаторов номеров

Пример:

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"
        }
    ]
}
*/

PS PHP-код не тестируется, поэтому я не уверен на 100%, работает ли он.

PPS Окончательное решение сильно зависит от деталей вашего проекта.

...