12

I have a collection TblStudent in mongodb like

       {
      "_id": ObjectId("5baa85041d7859f40d000029"),
       "Name": "John Doe",
       "RollNo": 12,
       "Class": "Ist"
        ....
       }

I have another collection TblRoute like

   {
   "_id": ObjectId("5baa818d1d78594010000029"),
   "Name": "New york City",
   "StopDetails": [
   {
    "StopId": "abc777",
    "Name": "Block no 3"
   },
   {
   "StopId": "abc888",
   "Name": "Block no 4"
   }
 ],
"NumberOfSeats": "10",
"StudentDetails": [
 {
   "StudentId": ObjectId("5baa85041d7859f40d000029"),
   "VehicleId": "7756"
  },
  {
   "StudentId": ObjectId("5baa85f61d7859401000002a"),
   "VehicleId": "7676"
 }
 ]
}

I am using mongodb 3.6 platform. I am using below lines of code

       $query = ['_id' => new MongoDB\BSON\ObjectID($this->id)];
    $cursor = $this->db->TblRoute->aggregate([
    ['$match' => $query],
    [
    '$lookup' =>
     [
       'from' => "TblStudent",
        'let' => ['StudentId' => '$StudentDetails.StudentId'],
        'pipeline' => [
          [ '$match' =>
             ['$expr' =>        
                ['$eq' => ['$StudentId',  '$$StudentId' ] ]  
             ]
          ],
           [ '$project' => ['Name' => 1, 'RollNo' => 1 ] ]
       ],
       'as' => "StudentDetails.StudentData"
     ]                   
    ] 
  ]);

I have been trying to fetch data from another collection but with certain fields only. I am trying to fetch student Name and RollNo fields from TblStudent inside TblRoute in order to make document array light weight. Normally the $lookup stage fetches all the fields from another collection.

I am trying the above code. It throws error message

"StudentDetails.StudentData" is coming empty 'StudentDetails' => MongoDB\Model\BSONDocument::__set_state(array( 'StudentData' => MongoDB\Model\BSONArray::__set_state(array( )), )), 

but I think that the code is not written correctly. The actual method might be different. Please help me in sorting out the problem.

I want the output to be something like

{
"_id": ObjectId("5baa818d1d78594010000029"),
"Name": "New york City",
"StopDetails": [
     .....
  ],
   "StudentDetails": [
   {
   "StudentId": ObjectId("5baa85041d7859f40d000029"),
   "VehicleId": "7756",
   "StudentData": [
      "Name": ..
      "RollNo":...
    ]
    },
    {
    "StudentId": ObjectId("5baa85f61d7859401000002a"),
    "VehicleId": "7676",
     "StudentData": [
      "Name": ..
      "RollNo":...
    ]
   }
   ]
  }
str8up7od
  • 338
  • 3
  • 15
Nida Amin
  • 735
  • 1
  • 8
  • 28
  • What is the error message ? – s7vr Oct 08 '18 at 19:37
  • Fatal error: Uncaught exception 'MongoDB\Driver\Exception\RuntimeException' with message ''StudentId' starts with an invalid character for a user variable name' in – Nida Amin Oct 08 '18 at 19:38
  • Okay try `[ '$lookup' => [ 'from' => "TblStudent", 'let' => ['studentid' => '$StudentDetails.StudentId'], 'pipeline' => [ [ '$match' => ['$expr' => ['$in' => ['$StudentId', '$$studentid' ] ] ] ], [ '$project' => ['Name' => 1, 'RollNo' => 1 ] ] ], 'as' => "StudentDetails.StudentData" ]`. From the docs _User variable names must begin with a lowercase ascii letter [a-z] or a non-ascii character_ – s7vr Oct 08 '18 at 19:40
  • Now that error message disappeared but "StudentDetails.StudentData" is coming empty 'StudentDetails' => MongoDB\Model\BSONDocument::__set_state(array( 'StudentData' => MongoDB\Model\BSONArray::__set_state(array( )), )), – Nida Amin Oct 08 '18 at 19:54
  • did you use $in instead of $eq in your $lookup stage ? – s7vr Oct 08 '18 at 19:55
  • Also please note that previously created StudentDetails embbeded document are overwritten with empty array due to StudentDetails.StudentData line – Nida Amin Oct 08 '18 at 19:55
  • i have used $in – Nida Amin Oct 08 '18 at 19:56
  • Sorry. I don't see anything wrong with the query. Can you try running query in mongo shell ? – s7vr Oct 08 '18 at 19:58
  • Please tell me that is the above written code right method to achieve the goal, – Nida Amin Oct 08 '18 at 20:01
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/181495/discussion-between-veeram-and-nida-amin). – s7vr Oct 08 '18 at 20:02

1 Answers1

15

Use the below aggregation.

Note from the docs

User variable names must begin with a lowercase ascii letter [a-z] or a non-ascii character.

So change the $let variable to studentid and also fixed other issues in code.

db.TblRoute.aggregate([
  {"$match":ObjectId("5baa818d1d78594010000029")},
  {"$lookup":{
    "from":"TblStudent",
    "let":{"studentid":"$StudentDetails.StudentId"},
    "pipeline":[
      {"$match":{"$expr":{"$in":["$_id","$$studentid"]}}},
      {"$project":{"Name":1,"RollNo":1}}
    ],
    "as":"StudentDetails.StudentData"
  }}
])
s7vr
  • 73,656
  • 11
  • 106
  • 127