1

I'm trying to implement an average calculation over a mongo dataset using MongoCollection()::aggregate(), but the functions returns a Cursor object and I can't figure out what I'm doing wrong.

This a sample of the dataset content:

{ word : "word", time : 1234, result  : "pass" }

This pipeline query works in the mongo console:

{"$group" : 
   {"_id" : "$result", 
    "meanTime" : {"$avg" :"$time"}
   }
}

This is my code:

    public function  getTimes($fields = array('correct','wrong','pass')){


    $group = ['$group'=> ["_id" => '$result', "meanTime" => ['$avg' =>'$time']]];

    $agg = $this->collection->aggregate(
                    [$group]
                    );
    return $agg;

}
/*
//This is the var_dump on $agg
object(MongoDB\Driver\Cursor)#82 (2) {
["cursor"]=>
array(17) {
["stamp"]=>
int(0)
["is_command"]=>
bool(false)
["sent"]=>
bool(true)
["done"]=>
bool(false)
["end_of_event"]=>
bool(false)
["in_exhaust"]=>
bool(false)
["has_fields"]=>
bool(false)
["query"]=>
object(stdClass)#76 (0) {
}
["fields"]=>
    object(stdClass)#74 (0) {
    }
    ["read_preference"]=>
    array(2) {
    ["mode"]=>
      int(1)
      ["tags"]=>
      array(0) {
    }
    }
    ["flags"]=>
    int(0)
    ["skip"]=>
    int(0)
    ["limit"]=>
    int(0)
    ["count"]=>
    int(2)
    ["batch_size"]=>
    int(0)
    ["ns"]=>
    string(23) "circular.intesavincente"
["current_doc"]=>
    object(stdClass)#83 (2) {
    ["_id"]=>
      string(4) "pass"
["meanTime"]=>
      float(338)
    }
  }
  ["server_id"]=>
  int(1)
}

//This is the json_encode output
{}

*/

I have tried to write the pipeline array with both array() construct and simplified [], but the result is unchanged. What I'm doing wrong? Thanks

1 Answer 1

3

You are using the MongoDB driver and mongo-php-library I guess. If so the result is such as should be. You could notice [meanTime] field in the result. You just need apply toArray() method to the resulting MongoDB\Driver\Cursor. Something like this (based on your initial code):

<?php
require 'vendor/autoload.php';

class Timer
{
    public $collection;

    public function getTimes()
    {
        $group = [
            '$group' => [
                "_id"      => '$result',
                "meanTime" => [
                    '$avg' => '$time',
                ],
            ],
        ];

        return $this->collection->aggregate([$group]);
    }
}

$timer = new Timer;
$m = new MongoDB\Client();
$db = $m->test;
$timer->collection = $db->so;
$cursor = $timer->getTimes();
$result = $cursor->toArray();
echo var_export($result[0]->bsonSerialize(), false);

//
// stdClass::__set_state(array(
// '_id' => 'pass',
// 'meanTime' => 1234,
//))

You can also see the library documentation to using various methods properly.

You could use the mongo.so extension to see more clear result but this extension is deprecated now.

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, I just realized that the object returned was a cursor instead of an array. Funny thing is I correctly converted to array a similar object a couple lines above that function. I guess Ballmer's peak is real

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.