Query builder mongodb index datetime - mongodb

I'm looking to execute custome query with doctrine odm in fulltext search and datetime range
Indexes are already generated on mongodb
Here is my code :
$search = $dm->createQueryBuilder('VideoBundle:Video');
if (isset($_POST['date']))
{
$from = new \DateTime($_POST['date']);
$to = new \DateTime('today');
$search->field('published')->range($from, $to);
}
$search->expr()->operator('$text', array(
'$search' => $_POST['searchvideo'],
));
$search->limit(50);
$query = $search->getQuery();
$search = $query->execute();
Query returned and executed by Doctrine Mongodb in Symfony profiler is :
db.Video.find().limit(50);
Any help?

Related

Yii2 MongoDB delete single row from document

I try this two way to delete but unable to do so:--
Try one:-
$query = new Query();
$query->delete()->from('table_name')->where(['disease_id' => 'A0PO919Q-12', 'status' => 1]);
Try Two:-
$collection = Yii::$app->mongodb->getCollection('table_name');
$collection->delete(['disease_id' => 'A0PO919Q-12']);
Can anyone try to delete data from mongo DB in Yii2 Framewrok
I find the solution
$collection = Yii::$app->mongodb->getCollection('table_name');
$collection->remove(['disease_id' => 'A0PO919Q-12']);

MongoDB PHP Date

In my database I have a document like this.
{
"_id" : ObjectId("5465508f453c9446d228b225"),
"category" : "animals",
"lastLocation" : "Wilpattu",
"lastSeenDate" : "2013-05-26",
"company" : "53fd9a3204ac58132377f807"
}
I want to check if the given date is in between two date ranges. I am using Codeigniter for front end development. In the model class I have written,
$connection =$this->Dbconnect->GetMongoCon();
$database = $connection->etsp;
$collection = $database->trackedObjects;
$start = $AnimalArray['fyear']. '-'.$AnimalArray['fmonth'].'-'.$AnimalArray['fday'];
$end = $AnimalArray['lyear']. '-'.$AnimalArray['lmonth'].'-'.$AnimalArray['lday'];
$searchCriteria = array(
'company' => $AnimalArray["Company"],
'lastSeenDate' =>array('$gt' => $start1, '$lte' => $end1)
);
$ReturnAnimalArray=$collection->find($searchCriteria);
But I can't query the date. From internet I have tried converting date into mongodb format.
$start1 = new MongoDate(strtotime(date($start )));
$end1 = new MongoDate(strtotime(date($end)));
But that also did not work. Any hint will be highly appreciated.
lastSeenDate is not MongodbDate format, may be you should like do this:
$js = "function() {
return this.lastSeenDate > '2013-02-18' && this.lastSeenDate <= '2014-09-28';
}";
$collection->find(array('$where' => $js));

Symfony2 app, MongoDB: Count all records matching criteria

In my controller I'm fetching limited number of objects (for pagination) like this:
$dm = $this->get('doctrine_mongodb');
$repo = $dm->getRepository('AcmeMyBundle:MyDocument');
$criteria = array(
'field1' => 'value1',
'field1' => 'value1',
);
$logs = $repo->findBy(
$criteria, /* criteria */
array($field => $direction), /* sort */
$limit, /* limit */
(($page-1)*$limit)?:null /* skip */
);
Now I like to get total number of records that meet the $criteria.
I was trying to count it like this:
$count = $repo->createQueryBuilder('MyDocument')
->count()->getQuery()->execute();
But it counts all records in collection. How can I apply $criteria to that counting query?
I need result as native MongoDB db.MyDocument.find({'field2': "value1", 'field2': "value2"}).count()
Done it like this:
$countQuery = $repo
->createQueryBuilder('MyDocument')
->requireIndexes(false)
;
foreach(array_filter($criteria) as $field=>$value){
$countQuery->field($field)->equals($value);
}
$count = $countQuery->count()->getQuery()->execute();

MongoDB & PHP - Returning a count of a nested array

Imagine I have a MonogDB collection containing documents as follows:
{name: 'Some Name', components: {ARRAY OF ITEMS}}
How can I return the name and the count of items in components?
Do I have to use a map/reduce?
I am using PHP's Mongo extension.
EDIT: Snippet of current code in PHP (working) but I just want count of the components
$fields = array(
'name', 'components'
);
$cursor = $this->collection->find(array(), $fields);
$cursor->sort(array('created_ts' => -1));
if (empty($cursor) == true) {
return array();
} else {
return iterator_to_array($cursor);
}
Thanks,
Jim
You could use map-reduce or you could use a simple group query as follows. Since I am assuming that your name property is a unique key, this should work even though it isn't a reason that you'd normally use the group function:
db.test.group({
key: { name:true },
reduce: function(obj,prev) {
var count = 0;
for(k in obj.components)
count++;
prev.count = count;
},
initial: { count: 0}
});
You mentioned that you have an array of components, but it appears that you are storing components as an object {} and not and array []. That is why I had to add the loop in the reduce function, to count all of the properties of the components object. If it were actually an array then you could simply use the .length property.
In PHP it would look something like this (from the Manual):
$keys = array('name' => 1);
$initial = array('count' => 0);
$reduce =<<<JS
function(obj,prev) {
var count = 0;
for(k in obj.components)
count++;
prev.count = count;
},
JS;
$m = new Mongo();
$db = $m->selectDB('Database');
$coll = $db->selectCollection('Collection');
$data = $coll->group($keys, $initial, $reduce);
Finally, I would strongly suggest that if you are trying to access the count of your components on a regular basis that you store the count as an additional property of the document and update it whenever it changes. If you are attempting to write queries that filter based on this count then you will also be able to add an index on that components property.
You could use db.eval() and write the calculation in JavaScript.
Jim-
These are two separate operations; Unless you want to leverage PHP's count on the results you get which you would then do something like:
$m = new Mongo();
$db = $m->selectDB('yourDB');
$collection = $db->selectCollection('MyCollection');
$cursor = $collection->find(array(), array("name"=>1, "components"=>1));
foreach($cursor as $key){
echo($key['name'].' components: '.count($key['components']);
}
Ran across this today, If your using the new driver with aggregate you can do this in php, ( given this schema )
{name: 'Some Name', components: {ARRAY OF ITEMS}}
In PHP:
$collection = (new Client())->db->my_collection;
$collection->aggregate([
'$match' => ['name' => 'Some Name'],
'$group' => [
'_id' => null,
'total'=> ['$sum' => "\$components"]
]
]);
The trick here with PHP is to escape the $ dollar sign, this is basically what the mongo documentation says when using size or sum
https://docs.mongodb.com/manual/reference/operator/aggregation/size/
https://docs.mongodb.com/manual/reference/operator/aggregation/sum/
The problem I had is mongo puts fields in as "$field" and PHP doesn't like that at all because of the way it does variable interpolation. However, once you escape the $, it works fine.
I think for this particular case you'd need to do something similar but with $project instead of $group Like this
$collection = (new Client())->db->my_collection;
$collection->aggregate([
'$match' => ['name' => 'Some Name'],
'$project' => [
'name' => "\$name",
'total'=> ['$sum' => "\$components"]
]
]);
This is an old question but seeing as there is no answer picked, I'll just leave this here.

Zend framework group by

I'm trying to do a group by using Zend framework. Here's my code:
$table = new TableClass();
$select = $table->select();
$select->from ("table", array("date", "column1" => "sum(column1)"));
$select->group ( array ("date") );
$results = $table->fetchAll ($select);
$result = $results[0];
$date = $result->date;
$column1 = $result->column1;
TableClass extends 'Zend_Db_Table_Abstract'.
I can see the query by looking at the mysql query log. The query is well formed - column1 is named in the query and the results look correct if I run the query in mysql workbench.
I cannot access the data in 'column1' - I always get this exception:
Uncaught exception 'Zend_Db_Table_Row_Exception' with message 'Specified column "column1" is not in the row'
I can however access the date column without issue.
I tried:
accessing the columns by array index:
$result[0]
but you get an exception (can't access the columns by index).
not using a column alias:
$select->from ("table", array("date", "sum(column1)"));
$column1 = $result["sum(column1)"];
but you get an exception (no such column "sum(column1)").
throwing in a Zend_Db_Expr:
"column1" => new Zend_Db_Expr ( "sum(column1)" )
but this doesn't help.
Some other examples I have seen suggest the use of the column names without aggregate functions, ie. "column1" instead of "sum(column1)" but that doesn't seem to me to be the answer - the query doesn't have any aggregate functions in it so mysql won't know what to do with it.
Any help appreciated.
Firstly, a quick tip for working with Zend_Db_Select (and by extension Zend_Db_Table_Select), you can view the generated SQL by invoking the toString method. It is vital to verify that your code generates the correct query before working with a result set:
$select = $table->select();
$select->from ("table", array("date", "column1" => "sum(column1)"));
$select->group ( array ("date") );
$sql = (string) $select; //Retrieve SQL as a string
Or simply
die($select); //print SQL
I wrote the following test script using your example and have no problems:
class Table extends Zend_Db_Table_Abstract
{
protected $_primary = 'id';
protected $_name = 'table';
}
$db = Zend_Db::factory('Pdo_Mysql', array(
'dbname' => 'test',
'username' => 'root',
'password' => '',
'host' => 'localhost'
));
$table = new Table($db);
$select = $table->select();
$select->from ($table, array("date", "column1" => new Zend_Db_Expr("sum(column1)")));
$select->group ( array ("date") );
$sql = (string) $select;
echo $sql;
$results = $table->fetchAll ($select);
$result = $results[0];
$date = $result->date;
$column1 = $result->column1;
echo '<br>' . $date . ': ' . $column1;
Use Zend_Debug::dump($result); to inspect data inside the Zend_Db_Table_Row if necessary.
In my case the SQL generated is as follows:
SELECT `table`.`date`, sum(column1) AS `column1` FROM `table` GROUP BY `date`