mongodb aggregation php - php

I'm using mongodb 2.1 and how to translate this query into php
db.counter.aggregate([
{ $match:{ page_id:123456 }},
{ $group:{_id:"$page_id",total:{$sum:"$pageview"}} }
]);
Thanks

You can use the 'command()' method in PHP to run the aggregation framework as a database command. The precise syntax for your sample query would be:
$conn = new Mongo("localhost:$port");
$db = $conn->test;
$result = $db->command (
array(
"aggregate" => "counter",
"pipeline" =>
array(
array( '$match' => array( 'page_id' => 123456 )),
array( '$group' => array( "_id" => '$page_id',
'total' => array( '$sum' => '$pageview')
)
)
)
)
);

Try:
$m = new MongoClient();
$con = $m->selectDB("dbName")->selectCollection("counter");
$cond = array(
array('$match' => array('page_id' =>123456)),
array(
'$group' => array(
'_id' => '$page_id',
'total' => array('$sum' => '$pageview'),
),
)
);
$out = $con->aggregate($cond);
print_r($out);
For more detail click here

Related

How do I group by on a dbref in MongoDB with Doctrine

I want to do an aggregation query where I can group by a dbref. This is what I've tried.
$aggregation = array(
array(
'$group' => array(
'_id' => '$foreign.$id',
'doc' => array(
'$last' => '$$ROOT'
)
)
),
array(
'$sort' => array(
'date' => -1
)
)
);
return $this->getDocumentManager()->getDocumentCollection('AppBundle:Collection')->aggregate($aggregation)->toArray();
But this attempt fails because you're not allowed to use the second $ sign in '$foreign.$id'. How can I do this query?
After a lot of searching I've found this Bug Ticket on the monogdb Jira which deals with basically this / an similar issue.
The last comment on this ticket offers an workaround to resolve the issue as an command line code. I've taken this solution and built it into an aggregation query which solved my problem.
$aggregation = array(
array(
'$addFields' => array(
'foreignId' => array(
'$arrayToObject' => array(
'$map' => array(
'input' => array(
'$objectToArray' => '$foreign'
),
'in' => array(
'k' => array(
'$cond' => array(
array(
'$eq' => array(
array(
'$substrCP' => array(
'$$this.k', 0, 1
)
),
array(
'$literal' => '$'
)
)
),
array(
'$substrCP' => array(
'$$this.k',1,['$strLenCP' => '$$this.k']
)
),
'$$this.k'
)
),
'v' => '$$this.v'
)
)
)
)
)
),
array(
'$group' => array(
'_id' => '$foreignId',
'doc' => array(
'$last' => '$$ROOT'
)
)
),
array(
'$sort' => array(
'date' => -1
)
)
);
$this->getDocumentManager()->getDocumentCollection('AppBundle:Collection')->aggregate($aggregation)->toArray();
This query gives me the correct and expected result.

How to remove waitedMS and ok from mongo db aggregation result?

I am performing aggregation command in mongodb php application like below lines of code.
<?php
$query = array('$or' => array(
array('employeeList'=>array('$exists' => false)),
array('employeeList'=>array('$eq' => null)),
array('employeeList'=>array('$eq' => ",")),
array('employeeList'=>array('$eq' => ""))
));
$pipeline = array(
array(
'$match' => $query
),
array(
'$lookup' => array(
'from' => 'userTbl',
'localField' => 'user_id',
'foreignField' => 'uid',
'as' => 'userdetails'
)
),
);
$output = $this->db->broadcastTbl->aggregate($pipeline);
$result =array();
array_push($result, $output);
Now the output is displayed as
[{"waitedMS":0,"result":[{"_id":{"$id":"58d7a6561d78597411000029"},"broadcast_id":35,"studentList":"","employeeList":"999","mailTitle":"hello","broadcastMessage":"how","emailSent":"0","userdetails":[]},{"_id":....
...
"ok":1}]
I want to remove "waitedMS":0. "result":, and "ok":1 from the json. The output should be like
[{"_id":{"$id":"58d7a6561d78597411000029"},"broadcast_id":35,"studentList":"","employeeList":"999","mailTitle":"hello","broadcastMessage":"how","emailSent":"0","userdetails":[]}, ...
]
Please help me !!!
All you need to do is access the "result" item. Don't push it onto another array.
<?php
$query = array('$or' => array(
array('employeeList'=>array('$exists' => false)),
array('employeeList'=>array('$eq' => null)),
array('employeeList'=>array('$eq' => ",")),
array('employeeList'=>array('$eq' => ""))
));
$pipeline = array(
array(
'$match' => $query
),
array(
'$lookup' => array(
'from' => 'userTbl',
'localField' => 'user_id',
'foreignField' => 'uid',
'as' => 'userdetails'
)
),
);
$output = $this->db->broadcastTbl->aggregate($pipeline);
$result = $output["result"];

How to convert mongoDB query into PHP?

My query is working in mongodb and produce output Properly. But same query i tried to run using php then it gives following error
Array
(
[ok] => 0
[errmsg] => A pipeline stage specification object must contain exactly one field.
[code] => 16435
)
Following is my MongoDB Query
db.sample_coll.aggregate(
{
$unwind: {
path:"$KeyValues",
includeArrayIndex:"arrayIndex",
preserveNullAndEmptyArrays:true
}
},
{
$project: {
timestamp:{
"$add":["$EventTS",{"$multiply":[60000,"$arrayIndex"]}]
} ,
"InputVolt":"$KeyValues.InputVolt",
arrayIndex:1
}
},
{
$match: {
$and: [
{InputVolt: {$ne: null}}
]
}
}
);
The Above query is converted in php
$pipeline = array(
array('$unwind' =>
array( 'path' => '$KeyValues'),
array( 'includeArrayIndex' => 'arrayIndex' ),
array( 'preserveNullAndEmptyArrays' => 'true' )
),
array(
'$project' => array(
'timestamp' => array(
'$add' => array(
'$EventTS',
array('$multiply' => array( 60000, '$arrayIndex' ))
)
),
array( 'InputVolt' => array( '$KeyValues', 'InputVolt' ) ) ,
array('arrayIndex' => 1)
)
),
array(
'$match' => array(
'$and' => array(
array('InputVolt' => array('$ne' => null )),
)
)
)
);
$result = $collection->aggregate($pipeline);
Kindly help to resolve this issue.
Thanks in advance
Your pipeline in PHP:
$pipeline = array(
array('$unwind' => array(
'path' => '$KeyValues',
'includeArrayIndex' => 'arrayIndex',
'preserveNullAndEmptyArrays' => true
)),
array('$project' => array(
'timestamp' => array(
'$add' => array('$EventTS', array('$multiply' => array(60000, '$arrayIndex')))
),
'InputVolt' => '$KeyValues.InputVolt',
'arrayIndex' => 1
)),
array('$match' => array(
'InputVolt' => array('$ne' => null)
))
);

to get sum in multiple conditions in mongodb and php

I've the following code to get the some of all price that have type 1 or a specific value but it dosen't work.
<?php
$m = new Mongo();
if (!$m)echo "Not Connected to database successfully";
$db =$m->mongo_project;
$collection = $db->prices;
$pipeline=array(
array(
'$match' => array(
'_id' => array(
'$type' =>1
)
)
),
array(
'$group' => array(
'_id' => '',
'count' => array(
'$sum' => '$price'
)
)
),
);
$out = $collection->aggregate($pipeline);
foreach ($out as $key=>$value) {
if($key=='result') {
$r=$value[0]['count'];
}
}
echo $r;?>
I think you mean a document that has a field "type" with a value of 1. The $type operator used here is a special MongoDB operator used to match certain BSON types. In this case you were asking for matching _id fields that were a "DOUBLE" type, or BSON type 1.
Correcting this:
$pipeline=array(
array(
'$match' => array(
'type' => 1
)
),
array(
'$group' => array(
'_id' => '',
'total' => array(
'$sum' => '$price'
)
)
),
);
Or you could just get the "sum" of the "price" values per each "type" value by passing that as the _id in your $group operation, instead. That way you can see everything at a glance:
$pipeline=array(
array(
'$group' => array(
'_id' => '$type',
'total' => array(
'$sum' => '$price'
)
)
),
);
In that context, '$type` means the value of the field.

Lithium framework multiple 'or' statements in a query (using mongoDB)

I have started work with lithium framework + mongoDB recently. I want to do a really simple query which contains multiple or statements.
I have articles in the DB with publish_up and publish_down fields. I want to fetch only those records/documents which pulbis_down field is highert than now OR null AND publish_up field lower than now OR null.
$items = $article::find('all', array(
'conditions' => array(
'$or' => array(
'$gt' => array('publish_down', $mongoDateNow),
'publish_down' => $mongDateNull
),
'$or' => array(
'$lt' => array('publish_up', $mongoDateNow),
'publish_up' => $mongDateNull
),
)
));
Of course this snippet is wrong hence the second or statement overwrites the first one (because the same array key).
I tried to wrap them into an individual array but gives error.
Any idea?
This query will fetch articles with (publish_down > now OR publish_down = null) AND (publish_up < now OR publish_up = null)
$items = Articles::find('all', array(
'conditions' => array(
'$or' => array(
array('publish_down' => array('$gt' => $mongoDateNow)),
array('publish_down' => null)
),
'$or' => array(
array('publish_up' => array('$lt' => $mongoDateNow)),
array('publish_up' => null)
),
)
));
I don't know about lithium but in PHP you can use multiple $OR as below
$items = $article::find('all', array(
'conditions' => array(
'$or' => array(
array(
'$gt' => array('publish_down', $mongoDateNow),
'publish_down' => $mongDateNull
),
array(
'$lt' => array('publish_up', $mongoDateNow),
'publish_up' => $mongDateNull
)
),
)
));
I think the correct answer is:
'$and' => array(
array(
'$or'=>array(
array('publish_up' => null),
array('publish_up' => array('$lt' => $mongoDateNow))
)
),
array(
'$or'=>array(
array('publish_down' => null),
array('publish_down' => array('$gt' => $mongoDateNow))
)
)
)

Categories