Symfony mongo-odm-aggregation-bundle sums - php

For start, I have to say I am new to mongo (3.2). I am using mongo-odm-aggregation-bundle for php framework Symfony (2.8.4). I want to get sums of some fields restricted by dates.
So far, I managed to get sums for all records:
$expr = new \Solution\MongoAggregation\Pipeline\Operators\Expr;
$aq = $this->manager->getCollection('AppBundle:UserDaySums')->createAggregateQuery()->group([
'_id' => 'client.$id',
'total' => $expr->sum('$aSum'),
])
Now, I'd like to restrict this query by dateFrom,dateTo and userId. I am not sure, how to do it. I know, I should probably use match function, but I don't know how. Or is there some better solution?
Thanks for replies!
KP

Yes, you can use the match function. For example, the following assumes you have the date variables for use in the query:
$expr = new \Solution\MongoAggregation\Pipeline\Operators\Expr;
$aq = $this->manager->getCollection('AppBundle:UserDaySums')->createAggregateQuery();
$dateFrom = new MongoDate(strtotime('-2 days'));
$dateTo = new MongoDate();
$userId = 'Xsgy62js0lb';
$result = $aq->match(['dateFrom'=>$dateFrom, 'dateTo'=>$dateTo, 'userId'=>$userId ])
->group(['_id'=>'client.$id', 'total'=>$expr->sum('$aSum') ])
->getQuery()->aggregate();

In my case, match() was somewhat tricky on a MongoId object.
This didn't work for me:
$userMongoId = "57321c7a2977f8de306ef648";
$aq ->match([ 'user.$id' => $expr->eq($userMongoId) ])
This worked:
$aq ->match([ 'user' => new \MongoId($userMongoId) ])
Tested on Symfony 3 with the SolutionMongoAggregationBundle, MongoDB version 3.2.6.

Related

zend framework paginator does not work?

I use ZendFramework Paginator and I have some code like this:
$defaultCount=1000;
$db = Zend_Db_Table::getDefaultAdapter();
$select = $db->select();
$select->from(array('u' => 'core_users'));
$select->join(array('ur' => 'core_users_roles'), 'u.uid = ur.uid');
$select->join(array('r' => 'core_roles'), 'r.rid = ur.rid');
$adapter=new Zend_Paginator_Adapter_DbSelect($select);
$adapter->setRowCount($db->select()->from('core_users',array(Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN =>'uid')));
$paginator= new Zend_Paginator($adapter);
$paginator->setItemCountPerPage($defaultCount);
$paginator->setCurrentPageNumber($page);
but ,i can not get all of my data from DbSelect Adapter.when i remove $defaultCount , it always give me 20 total data (default ,I guess). should i use single table ?
$db->select()->from('core_users',array(Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN =>'uid'))
give me wrong number. I use hard code ,works on me.

Why doesn't this PHP MongoDB query return any results even though there is one?

I have a collection of users and users have a meta.create_date field which is an ISODate as seen below. I am trying to count how many users were created in the last N days. I have the following in the database:
{
"_id" : ObjectId("51e61fa16803fa40130a0581"),
"meta" : {
"create_date" : ISODate("2013-07-17T04:37:53.355Z")
}
}
My PHP code:
$daysAgo = new MongoDate(date('c', strtotime('-7 days')));
$query = array(
'meta.create_date' => array(
'$gte' => $daysAgo,
)
);
$result = $this->db->users->count($query);
I have also tried specifying a range using '$gte' and '$lte' where $lte => today.
However, result is coming back as 0. So what is going on here?
MongoDate() takes int time(). So, passing in a php date() to the constructor does not work. This is the proper way:
$daysAgo = new MongoDate(strtotime('-7 days'));

cakephp created query for exact date

Trying to figure out how to find all records from database that were created on a specific day but I'm having a hard time coming up with the necessary conditions. This is what I have so far:
$date = new DateTime('2012-11-25');
$users = $this->User->find('all', array('conditions' => array('User.created > ' => $date)));
But this is giving me more than just the specified day. How can I adjust the condition so that it returns all users that were created only on November 25th?
Your code has a greater than symbol in it.
$users = $this->User->find('all', array('conditions' => array('User.created > ' => $date)));
try without:
$users = $this->User->find('all', array('conditions' => array('User.created' => $date)));
you should use the CakeTime method for this or manually assert that you only check on the date part of this particular day.
http://book.cakephp.org/2.0/en/core-utility-libraries/time.html#CakeTime::dayAsSql
'conditions' => CakeTime::dayAsSql($date, 'created')
After playing around, I finally was able to get it to work. Hopefully this can help somebody else out there that runs across the same situation:
$date = new DateTime('2012-11-25');
$users = $this->User->find('all', array('conditions' => CakeTime::dayAsSql($date, $date, 'User.created')));
The key was making sure to provide the $date twice.

Use of "$or" condition is not working

I am developing a search portal, so I need to find the searched text on more than one field.
I am trying to use the advanced query of MongoDB in PHP.
My code is:
$mongo = new MongoDBCONN();
$jobCollection = $mongo->select('jobs', $mongo);
$advanceQuery=array('orgId' => '21')
$query_q=array('$or'=>array(
array("jobTitle"=>new MongoRegex("/$search/i")),
array("jobLocationCity"=>new MongoRegex("/$search/i")),
array('jobLocationCountry'=>new MongoRegex("/$search/i"))
));
$advanceQuery=array_merge($advanceQuery,$query_q);
$jobCollection->find($advanceQuery);
It returns NULL every time, whereas MongoRegex is working fine, because when I use it to search on only one field it works.
$search is post as input text.
I found the answer on my own, actually this was a version problem. I was using 1.4.4, but after update to 1.7.4 it is working. On the mongo website I found that the "or" operator was included only from version 1.7.x onwards.
$regexObj = new MongoRegex("/$search_term/i");
$where = array(
'$or' => array(
array("Name" => $regexObj),
array("image.caption.text" => $regexObj),
array("image.user.username" => $regexObj)
)
);
$cursor = $collection->find($where);
// Parsing the results
while ($cursor->hasNext())
{
$obj = $cursor->getNext();
$profile_image = $obj['image']['user']['profile_picture'];
}
If you need to combine the regex with another operator, you need to use the $regex clause. That one is missing in your code example. Please read again about how to query with regulars expressions.

Complex query implying dates

I'd like to return the customers from Magento who where created the day before OR who where updated the day before. I tried to play with addFieldToFilter, without any success.
I also tried to manipulate Zend_Db_Select, no success.
So now I'm stuck!
Here are some of my tries :
$customer = Mage::getModel('customer/customer');
$customers = $customer
->getCollection()
->getSelect()
->where("updated_at >= ? AND updated_at <= ?",$this->getFrom(), $this->getTo())
->orWhere("e.created_at >= ? AND e.created_at <= ?", $this->getFrom(), $this->getTo());
Or
->addFieldToFilter(
array(
array('attribute'=>'updated_at', 'gteq'=>$this->getFrom()),
array('attribute'=>'created_at', 'gteq'=>$this->getFrom())
),
'',
'left'
);
Thanks
I'd recommend against directly manipulating the select unless it's absolutely necessary and you know exactly what's going on behind the scenes in your version of Magento.
The following syntax should handle the tricky parts for you
$c = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToFilter(array(
array('attribute'=>'updated_at','from'=>'2010-05-12','to'=>'2010-05-30'),
array('attribute'=>'created_at','from'=>'2010-05-12','to'=>'2010-05-13')
));
var_dump( (string) $c->getSelect());
var_dump(count($c));
all you'll need to do is drop in the date ranges you want.
It is enough to use updated_at as your filter attribute, because it is set to current datetime when a user is created. So by filtering with this field you will get both new users and those who are not new but were updated in the given period. Here's the code to look for users updated or created during the last 24 hours:
$customers = Mage::getModel('customer/customer')->getCollection();
$customers->addAttributeToFilter('updated_at', array('gt' => date("Y-m-d H:i:s", time()-60*60*24)));
foreach($customers as $customer) {
//do sth
}
Thanks to Alan and Silvo, here is what I wrote :
->addAttributeToFilter(array(
array('attribute'=>'updated_at','from'=>$this->getFrom(),'to'=>$this->getTo())
));
Both answers were usefull. Thank you!

Categories