Map Reduce in Mongo, Convert mongo query to php mongo - php

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')))
));

Related

Yii2 MongoDB distinct count

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

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.

how to use $bit operator to query in mongodb with php

i have a document like bellow, now i will to figure out which element in friendsR whose readable & 2 is grater than 0. anyone here can help me? thank you.
[code]
$doc = array('friendsR' => array(
array('friend_id'=>100, 'readable' => 7, 'bridge'=>5),
array('friend_id'=>100, 'readable' => 7, 'bridge'=>6),
array('friend_id'=>100, 'readable' => 7, 'bridge'=>7))
);
datamodel()->insert($doc);
$macher = array('$bit' => array( 'friendsR.$.readable' => array('and'=>2) ));
$cursor = datamodel()->find($macher);
[/code]
The $bit operator is an "update operator", so it is used to change values and not query them.
If you need this sort of query you need a JavaScript evaluation such as $where:
For a document that looks like this in the shell:
{
"friendsR": [
{ 'friend_id': 100, 'readable': 7, 'bridge': 5 },
{ 'friend_id': 100, 'readable': 7, 'bridge': 6 },
{ 'friend_id': 100, 'readable': 7, 'bridge': 7 }
]
}
To just find documents that have a matching element you would do this:
$macher = array(
'$where' => new MongoCode("function(){
return this.friendsR.some(function(x) {
return ( x.readable & 2 ) > 0
})
}")
);
To actually return "which elements" matched you would again have to do something like this with mapReduce. It will "mark" which items in the array met the condition and only return documents where at least one array member that matches.
$map = new MongoCode("function(){
this.friendsR.forEach(function(friend) {
friend.macthed = ( ( friend.readable & 2 ) > 0 );
});
if ( this.friendsR.some(function(x) { return x.matched }) )
emit( this._id, this );
}");
$reduce = new MongoCode("function(){}");
$result = $db->command(array(
"mapreduce" => "collection_name",
"map" => $map,
"reduce" => $reduce,
"out" => array( "inline" => 1 )
));
There are no built in operators for bitwise evaluation so JavaScript is your only option where it is available.
Note that the mapReduce is a command and must be run from a Db object, the result is either returned inline as shown or output to another collection. This does not return a cursor. See the official documentation on mapReduce for more information.

mongodb: finding the highest numeric value of a column

I have MongoDB collection of documents containing several fields. One of the columns/fields should be numeric only, but some of these fields contain non-numerical (corrupt) data as string values. I should find the highest numerical value of this column, excluding the corrupt, non-numerical data. I am aware of the question Getting the highest value of a column in MongoDB, but AFAIK, this extended case was not covered.
The example below depicts the issue. For the highest value, the document with "age": 70 should be returned:
[
{
"id": "aa001",
"age": "90"
},
{
"id": "bb002",
"age": 70
},
{
"id": "cc003",
"age": 20,
}
]
Providing a PHP example for the find() / findOne() query would be of much help. Thanks a lot!
JohnnyHK came up with the perfect solution. Here's the working PHP code:
$cursor = $collection->find(array('age' => array('$not' => array('$type' => 2))), array('age' => 1));
$cursor->sort(array('age' => -1))->limit(1);
You can use the $type operator with $not in your query to exclude docs where age is a string. In the shell your query would look like:
db.test.find({age: {$not: {$type: 2}}}).sort({age: -1}).limit(1)
Or in PHP from Martti:
$cursor = $collection->find(array('age' => array('$not' => array('$type' => 2))), array('age' => 1));
$cursor->sort(array('price' => -1))->limit(1);
with PHP driver (mongodb)
using findOne()
$filter=[];
$options = ['sort' => ['age' => -1]]; // -1 is for DESC
$result = $collection->findOne(filter, $options);
$maxAge = $result['age']
You can use aggregate function to get maximum number from collections like this.
$data=$collection->aggregate(array
( '$group'=>
array('_id'=>'',
'age'=>array('$max'=>'$age'.)
)
)
);
This works for me
$options = ['limit' => 100,'skip' => 0, 'projection' => ['score' => ['$meta' => 'textScore']], 'sort' => ['score' => ['$meta' => 'textScore']]];

query with a field in several conditions in mongodb

I need to make a query like this:
db.subscribers.find({LISTID: 59, {$or: [{LANG: {$in: ['English', 'Spanish']} },
{LANG: {$nin: ['Russian']} }]} });
It's supposed to get all subscribers from listid 59, who know English or Spanish or(and) doesn't know Russian. Instead of language there could be any field that can have multiple values.
It looks like this query works in mongodb console.
In this case one field can be in several conditions.
I there is the same field wouldn't be in several conditions, maybe it could be something like:
$collection->find(array('LISTID' => $listId,
array('$or' = array(LANG => array('$in' => array('English','Spanish')),
/*some other condition united with OR*/
)));
How to make this query in php?
It's supposed to get all subscribers from listid 59, who know English or Spanish and doesn't know Chinese.
If that's the objective of your query (I assume you mean "Russian" instead of "Chinese"), I don't see how your original console query works:
db.subscribers.find({
LISTID: 59,
{ $or: [
{ LANG: { $in: ["English", "Spanish"] } },
{ LANG: { $nin: ["Russian"] } }
] }
});
$or needn't be nested in its own object according to the documentation. Also, if you're looking for documents with a given LISTID that know two languages but not another, $and seems more appropriate:
db.subscribers.find({
LISTID: 59,
$and: [
{ LANG: { $in: ["English", "Spanish"] } },
{ LANG: { $ne: "Russian" } }
]
});
This would translate to PHP as:
$collection->find(array(
'LISTID' => $listId,
'$and' => array(
array('LANG' => array('$in' => array('English', 'Spanish'))),
array('LANG' => array('$ne' => 'Russian')),
),
));
I think the solution is something like this:
$number = $collection->find(array('LISTID' => $listId,
'$or' => array( array('LANG' => array('$in' => array('English', 'Spanish'))),
array('LANG' => array('$nin' => array('Russian'))),
) ))->count();
// Find record according to specific column
$getfollower = $dbnew1->find(array('follower' => $follower),
array('page_name' => 1, 'id'=>1, '_id'=>0));

Categories