Yii2 MongoDB distinct count - php

How to get count distinct values from the collection using query?
Now I am using this solution:
$collection = Yii::$app->mongodb->getCollection('collection_name');
$result = $collection->distinct('field_id');
return count($result);
Collection example:
{
{a: 2},
{a: 2},
{b: 3},
{c: 4}
}
Result must be:
3

You can use the aggregation framework for this:
$collection = Yii::$app->mongodb->getCollection('collection_name');
$result = $collection->aggregate(
array('$group' => array(
'_id' => '$field_id'
)),
array('$group' => array(
'_id' => 1,
'count' => array( '$sum' => 1 )
))
);

Try this not tested but you can get your results, make some changes if exception occur.
use yii\mongodb\Query;
$query = new Query;
$count = $query->from('collection_name')->distinct('field_id')->count();
More detail

Related

How to update multiple data in CakePHP

I need to save multiple rows with the different condition for each row.
Like :
Update orderdetails SET data = "'.$json1.'" WHERE order_id = 1;
Update orderdetails SET data = "'.$json2.'" WHERE order_id = 2;
Update orderdetails SET data = "'.$json3.'" WHERE order_id = 3;
Update orderdetails SET data = "'.$json4.'" WHERE order_id = 4;
Update orderdetails SET data = "'.$json5.'" WHERE order_id = 5;
I know the single row updation method of CakePHP, that I can run 5 times form to update all row.
But I want to save this by just only one line code that can run above query.
My Code
$update = array(
array('data' => $json1,'order_id' => 1),
array('data' => $json2,'order_id' => 2),
array('data' => $json3,'order_id' => 3),
array('data' => $json4,'order_id' => 4),
array('data' => $json5,'order_id' => 5)
);
$this->Orderdetail->saveMany($update);
So, is there any way in CakePHP to achieve it...?
If I understand the above problem currently, you can achieve this by using the saveMany function in cakePHP. All you have to do is convert the data that you want to save in the form of an array and pass that single array to the saveMany function.
See here for more details
Here is a code sample for the above details in cakePHP 3:
$saveData = [
[
'order_id' => 1,
'data' => $json1
],
[
'order_id' => 2,
'data' => $json2
],
[
'order_id' => 3,
'data' => $json3
],
[
'order_id' => 4,
'data' => $json4
],
[
'order_id' => 5,
'data' => $json5
]
];
$orderDetails = TableRegistry::get('Orderdetails');
$entities = $orderDetails->newEntities($saveData);
$result = $orderDetails->saveMany($entities);
For cakePHP 2.x:
See here for more details
Hope this is what you are looking for.
Edit: Based on the updated requirements, I guess the only way to achieve it is to make a custom query by using the Model->query method. You'll have to form a custom query for that which updates all the records in one go.

Mongo mapper use aggregation framework

Can someone please point out my error, trying to sum a field(amount) using userId field?
https://fatfreeframework.com/3.6/mongo-mapper
Here is my code, this is returning me all documents matched with userId but not the sum.
$f3 = \Base::instance();
$mapper = new \DB\Mongo\Mapper($f3->get('MongoDB'),'transactions');
$filter = array('userId'=>'452');
$options = array(
array(
'group' => array(
'_id' => array('userId' => $userId),
'amount' => array('$sum' => 'amount')
)
)
);
$data = $mapper->find($filter, $options);
echo "<pre>";
print_r($data);
exit;
The mongo mapper uses the db.collection.group() method rather than the aggregation framework. Therefore you won't be able to call accumulators such as $sum.
Instead you must use the following syntax:
$group = [
'keys'=>['userId'=>1],
'initial'=>['sum'=>0],
'reduce'=>'function(obj,result){result.sum+=obj.amount;}',
'finalize'=>'function(result){}',
);
$data = $mapper->find($filter, ['group'=>$group]);

Complex statement in MongoDB AND & OR conditions

Continuing on my project, I need to translate some SQL statements to mongoDB
My SQL Statement is:
Delete from 'table' where proc_id = $xxx and (day_id < $day OR day_id > $anotherDay)
Now my condition array is this:
$condicion = array(
'proc_id' => $xxx,
'$or' => array(
'day_id' => array(
'$lt' => $day,
'$gt' => $anotherDay
)
)
);
The function made for delete in mongo collections returns cannot delete...
Some help please?
Each "day_id" would be in it's own $or argument:
$query = array(
'proc_id' = > $xxx,
'$or' => array(
array( 'day_id' => array ( '$lt' => $day ) ),
array( 'day_id' => array ( '$gt' => $anotherDay ) ),
)
)
That is how $or conditions work as a "list" of possible expressions.
The JSON syntax is clearer to visualise:
{
"proc_id": $xxx,
"$or": [
{ "day_id": { "$lt": $day } },
{ "day_id": { "$gt": $anotherDay }}
]
}
Since there is a very clear distinction between a "list" and an "object" definition. $or conditions are "lists" of "objects", and that means you list the full condition just as if it were a query in itself. Since this is not called within an $elemMatch.
And of course the "DELETE" part is the .remove() method:
$collection->remove($query)
There are general examples and resources in the core documentation SQL to MongoDB Mapping Chart, where if the examples there do not immediately help, the linked articles and presentations should.

Equivalent of mysql max and min functions in mongo?

How can i write the below query in mongo?
select max(priority) as max, min(priority) as min from queue group by user
I'll highly appreciate if you provide a solution in PHP.
Thank you
Queries like this are performed with the aggregation framwework and the .aggregate() method. They use a $group pipeline stage with the $min and $max operators.
db.collection.aggregate([
{ "$group": {
"_id": "$user",
"max": { "$max": "$priority" },
"min": { "$min": "$priority" }
}}
])
Or more to PHP syntax:
$collection->aggregate(array(
array(
'$group' => array (
'_id' => '$user',
'max' => array( '$max' => '$priority' ),
'min' => array( '$min' => '$priority' )
)
)
));
Also see the SQL to Aggregation Mapping Chart in the documentation

Map Reduce in Mongo, Convert mongo query to php mongo

I had a query in mongo which looks like
db.Table_Name.group({
"key": { "Camp": true },
"initial": { "Clicks": 0 },
"reduce": function(obj, prev) {
prev.Clicks = prev.Clicks + obj.Clicks-0;
},
"cond": { "Date": { $gte: "2012-10-26", $lte: "2012-10-28" } }
});
I want to use this code in php. I tried all the possible ways. Can any one help me out from this problem. Even I followed this http://php.net/manual/en/mongodb.command.php Please any one help me out.
I tried this
$reduce = new MongoCode(
"function(obj, prev) {prev.Clicks = prev.Clicks + obj.Clicks-0;}"
);
$result = $db_1->command(array(
'mapreduce' => 'Collection_Name',
'key' => array("Camp" => true),
'initial' => array('Clicks' => 0),
'reduce' => $reduce,
'cond' => array(
'Date' => array('$gte' => '2010-07-12' , '$lte' => '2013-07-12')
),
));
Have you tried using MongoCollection::group? For your example, it might look something like this (not tested).
$keys = array("Camp" => 1);
$initial = array("Clicks" => 0);
$reduce = "function(obj, prev) {prev.Clicks = prev.Clicks + obj.Clicks-0;}";
$condition = array(
'Date' => array('$gte' => '2010-07-12', '$lte' => '2013-07-12')
);
$result = $collection->group($keys, $initial, $reduce, $condition);
Also, you should try to embrace the MongoDB terminology, i know it's just an example, but Table_Name should be Collection_Name as MongoDb does not have tables.
You could use the group command here but it is:
Slow
Basically a Map Reduce
JavaScript
Normally does not work with sharding (some people have made it)
Is deprecated in favour of the aggregation framework
Instead a better option would be to use the aggregation framework:
$mongo->db->collection->aggregate(array(
array('$match'=>array('date'=>array('$gte' => '2010-07-12','$lte' => '2013-07-12'))),
array('$group'=>array('_id'=>'$Camp', 'sum_clicks'=>array('$sum'=>'$Clicks')))
));

Categories