Search code examples
phpmongodbaggregation-frameworkphp-mongodb

Uncaught exception 'MongoDB\Driver\Exception\RuntimeException' with message 'An object representing an expression must have exactly one field:


I have written like below lines of code

         $cursor = $this->collection->aggregate(array(
             array(
                   '$match' => array(
                                "_id" => new MongoDB\BSON\ObjectID($this->id)
                                )
                  ),
             array(
                  '$project' => array(
                  'AllotmentsDetails' => array(
                  '$filter' => array(
                  'input' => '$AllotmentsDetails',
                  'as' => 'allot',
                  'cond' => array(
                   '$and' => array(
                  '$lt' => array('$$allot.ToDate', new MongoDB\BSON\UTCDateTime((new DateTime())->getTimestamp() * 1000)),
                  '$eq' => array('$$allotment.RoomId', $this->RoomId)
                     )
                   )
                  )
                 ),
                )
              )
            ))->toArray();

It is throwing error message " Uncaught exception 'MongoDB\Driver\Exception\RuntimeException' with message 'An object representing an expression must have exactly one field:"

Please help!!!


Solution

  • Just missing array notations and matching up in some wrong places:

    $pipeline = array(
      array( '$match' => array(
        "_id" => new MongoDB\BSON\ObjectID($this->id)
      )),
      array('$project' => array(
        'AllotmentsDetails' => array(
          '$filter' => array(
            'input' => '$AllotmentsDetails',
            'as' => 'allotment',
            'cond' => array(
              '$and' => array(
                array('$lt' => array(
                  '$$allotment.ToDate',
                  new MongoDB\BSON\UTCDateTime((new DateTime())->getTimestamp() * 1000)
                )),
                array('$eq' => array('$$allotment.RoomId', $this->RoomId))
              )
            )
          )
        )
      ))
    );
    
    $cursor = $this->collection->aggregate($pipeline)->toArray();
    

    or since we are in a modern world, a bit easier to read:

    $pipeline = [
      ['$match' => [
        "_id" => new MongoDB\BSON\ObjectID($this->id)
      ]],
      ['$project' => [
        'AllotmentsDetails' => [
          '$filter' => [
            'input' => '$AllotmentsDetails',
            'as' => 'allotment',
            'cond' => [
              '$and' => [
                ['$lt' => [
                  '$$allotment.ToDate',
                  new MongoDB\BSON\UTCDateTime((new DateTime())->getTimestamp() * 1000)
                ]],
                ['$eq' => ['$$allotment.RoomId', $this->RoomId] ]
              ]
            ]
          ]
        ]
      ]]
    ];
    
    $cursor = $this->collection->aggregate($pipeline)->toArray();
    

    I suggest a better editor and also to use json_encode() on your data structures in order to check that the generated JSON matches what you see as examples in the documentation.