PHP Mongo:command not found - php

I have been trying to use the mongo::command in PHP to build a MapReduce but every time I run my code I get the following error: PHP Fatal Error, call to undefined method "mongo:command"
My Code:
try {
$map = new MongoCode("function() {
if (!this.tags) {
return;
}
for (index in this.tags) {
emit(this.tags[index], 1);
}");
$reduce = new MongoCode("function(previous, current) {
var count = 0;
for (index in current) {
count += current[index];
}
return count;
}");
$tags = $this->db->command(array( //Line the error is found on
"mapreduce" => "blog",
"map" => $map,
"reduce" => $reduce));
$con=$this->db->selectCollection($tags['result'])->find();
var_dump($con);
}
catch(MongoCursorException $e) {
echo "error message: ".$e->getMessage()."\n";
echo "error code: ".$e->getCode()."\n";
}
Please note $this->db refers to my connection (previously defined) and blog is the collection.
For reference I have used: http://php.net/manual/en/mongodb.command.php
The OS I use is Ubuntu 12.04 and I've double checked both php.ini files which both include mongo.so - I can do normal queries with mongodb like inserting and fetching data, its just the command seems not to work.

do you select collection like $d = $m->demo;
php.net:
<?php
$m = new MongoClient();
$d = $m->demo;
$c = $d->poiConcat;
$r = $d->command(array(
'geoNear' => "poiConcat", // Search in the poiConcat collection
'near' => array(-0.08, 51.48), // Search near 51.48°N, 0.08°E
'spherical' => true, // Enable spherical search
'num' => 5, // Maximum 5 returned documents
));
print_r($r);
?>
i think in your code you didn't select collection $d = $this->db->demo; put collection name instead of demo
try {
$map = new MongoCode("function() {
if (!this.tags) {
return;
}
for (index in this.tags) {
emit(this.tags[index], 1);
}");
$reduce = new MongoCode("function(previous, current) {
var count = 0;
for (index in current) {
count += current[index];
}
return count;
}");
$d = $this->db->demo;// attention
$tags = $d->command(array( //Line the error is found on
"mapreduce" => "blog",
"map" => $map,
"reduce" => $reduce));
$con=$d->selectCollection($tags['result'])->find();
var_dump($con);
}
catch(MongoCursorException $e) {
echo "error message: ".$e->getMessage()."\n";
echo "error code: ".$e->getCode()."\n";
}
Edit Sample:i Do this sample see it
try {
$map = new MongoCode("function() { emit(this.user_id,1); }");
$reduce = new MongoCode("function(k, vals) { ".
"var sum = 0;".
"for (var i in vals) {".
"sum += vals[i];".
"}".
"return sum; }");
$db=new Mongo("mongodb://sepidar:123#localhost:27017/admin");
$d = $db->SepidarSoft_CBMS;// attention
$tags = $d->command(array( //Line the error is found on
'mapReduce'=>'RunUser',
"map" => $map,
"reduce" => $reduce,
"out" => array('merge'=>'SepidarSoft_CBMS', 'db'=> 'RunUser')
));
print_r($tags);
}
catch(MongoCursorException $e) {
echo "error message: ".$e->getMessage()."\n";
echo "error code: ".$e->getCode()."\n";
}
result
Array
(
[result] => Array
(
[db] => RunUser
[collection] => SepidarSoft_CBMS
)
[timeMillis] => 2
[counts] => Array
(
[input] => 1
[emit] => 1
[reduce] => 0
[output] => 1
)
[ok] => 1
)

Related

Google Task API PHP: Setting the TaskList ID & "Invalid task list ID" error

I'm trying to loop through task lists in order to generate a list of tasks using the Google Task PHP library.
I have:
Done all the credential stuff & can call the API
I can get task lists
A list of tasks for the respective task list output correctly using the ids generated from the point above & the tasklist parameter in Task API explorer
Where I'm stuck:
I'm not sure if I'm calling the 1) wrong method or 2) passing the wrong parameter to get a list of tasks for a respective tasklist id.
My code:
function getGcalTasks(){
$client = $this->getGcalTaskClient();
try {
$service = new Google_Service_Tasks($client);
$optParamLists = array(
'maxResults' => 10,
);
$result_lists = $service->tasklists->listTasklists($optParamLists);
if (
is_array($result_lists->getItems())
&& count($result_lists->getItems())
) {
foreach ($result_lists->getItems() as $tasklist) {
$taskListId = trim($tasklist->getId());
$taskListTitle = trim($tasklist->getTitle());
if(
$taskListId
){
$optParamsTasks = array(
// I've tried all of the below and still get: "Invalid task list ID",
'id' => $taskListId,
'kind' => 'tasks#taskList',
'title' => $taskListTitle,
//'tasklist' => $taskListId,
//'taskList' => $taskListId,
//'tasklistId' => $taskListId,
//'listName' => $taskListTitle,
);
$result_tasks = $service->tasks->listTasks($optParamsTasks);
}
}
}
} catch (Exception $e) {
log_message('error',$e->getMessage());
}
}
Welp, I took a look a few minutes later and realized that listTasks() only accepts one parameter, the id. The code below is working for me:
function getGcalTasks(){
$client = $this->getGcalTaskClient();
$tasks = array();
try {
$service = new Google_Service_Tasks($client);
$optParamLists = array(
'maxResults' => 10,
);
$result_lists = $service->tasklists->listTasklists($optParamLists);
if (
is_array($result_lists->getItems())
&& count($result_lists->getItems())
) {
foreach ($result_lists->getItems() as $tasklist) {
$taskListId = trim($tasklist->getId());
$taskListTitle = trim($tasklist->getTitle());
if(
$taskListId
){
$optParamsTasks = array(
'tasklist' => $taskListId,
);
$result_tasks = $service->tasks->listTasks($taskListId);
$tasks[] = $result_tasks->getItems();
}
}
return $tasks;
}
} catch (Exception $e) {
log_message('error',$e->getMessage());
}
}

Add data inside documents in Mongo DB using PHP

I want to insert data in Mongo database using PHP script, in year wise documents so that it may look like this (All years in one document);
cars{
2017{
car=Motorolla
color = blue
}
2016{
car=Toyota
color = green
}
2015{
car=Corolla
color = black
}
}
I wanted to add the document but it prompts
Document can't have $ prefixed field names: $years[0]
Is it possible to make such schema in Mongo using PHP?
Code
<?php
try {
$car = 'Motorolla';
$color = 'blue';
//$car = 'Toyota';
//$color = 'green';
//$car = 'Corolla';
//$color = 'black';
$years = array(2017, 2016, 2015);
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulkWriteManager = new MongoDB\Driver\BulkWrite;
$document = ['_id' => new MongoDB\BSON\ObjectID, '$years[0]' => $car, '$years[1]' => $color]; // Making a query type
try {
$bulkWriteManager->insert($document); // Inserting Document
echo 1;
} catch(MongoCursorException $e) {
/* handle the exception */
echo 0;
}
$manager->executeBulkWrite('dbName.carsCol', $bulkWriteManager); // Going to DB and Collection
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
}
?>
I do not want to add whole car object at once. I want to add Year object every time. Any help will be appreciable.
OR
Any relative answer so that I may get the data from Mongo Database according to the year?
Edit1
For first time creation. - Credits goes to #Veeram
<?php
try {
$car = 'Malibu';
$color = 'red';
$years = array(2017);
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulkWriteManager = new MongoDB\Driver\BulkWrite;
//{"car":"chevy", "color":"black", year: 2017}
$insert = ['car' => $car, 'color' => $color, 'year' => $years[0]];
try {
$bulkWriteManager -> insert($insert); // Inserting Document
echo 1;
} catch (MongoCursorException $e) {
echo 0;
}
$manager->executeBulkWrite('dbName.mycol', $bulkWriteManager); // Going to DB and Collection
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
echo "In file:", $e->getFile(), "\n";
echo "On line:", $e->getLine(), "\n";
}
?>
For the updation- Credits goes to #Veeram
<?php
try {
$car = 'ChangedCar';
$color = 'changedColor';
$years = array(2017);
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulkWriteManager = new MongoDB\Driver\BulkWrite;
$query = ['cars.year' => $years[0]];
//{ $push: { "cars.$.data": { "car":"chevy", "color":"black"} }}
$update = ['$push'=> ['cars.$.data'=>['car' => $car, 'color' => $color]]];
try {
$bulkWriteManager->update($query, $update); // Inserting Document
} catch(MongoCursorException $e) {
}
$manager->executeBulkWrite('dbName.mycol', $bulkWriteManager); // Going to DB and Collection
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
}
?>
The problem in this code is that it successfully insert the data for the first time but when i update the data it does not update it.
Example:
There is a document named as cars . Insert the data with object of year in one document. Let's say the Object is 2017, it contains color and car Model. As showing below; (Multiple objects with years. Year is unique in whole document.)
cars{
2017{
car=Motorolla
color = blue
}
2016{
car=Toyota
color = green
}
2015{
car=Corolla
color = black
}
}
If I want to update just make an object of 2017 like 2017{car=Updated-Motorolla color =Updated-blue} and insert in the document. It should update only the year 2017 object in side the document.
cars{
2017{
car=Updated-Motorolla
color =Updated-blue
}
2016{
car=Toyota
color = green
}
2015{
car=Corolla
color = black
}
}
You can try something like this. Its not possible to perform all the Mongo db operations just based off key as a value.
The first solution is written to stay close to OP's design.
Assuming you can add a key to the year.
{
"cars": [{
"year": "2017",
"data": [{
"car": "Motorolla",
"color": "blue"
}]
}, {
"year": "2016",
"data": [{
"car": "Toyota",
"color": "green"
}]
}]
}
Makes it easy to reference the year by its value.
For example to add a new value into the data array for year 2017. You can try the below code.
Uses update positional $ operator.
query part to reference the array where 2017 record is stored.
update part using push to add the new car record to the existing data array for 2017 row.
<?php
try {
$car = 'Malibu';
$color = 'blue';
$years = [2017];
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulkWriteManager = new MongoDB\Driver\BulkWrite;
//{"cars.year":2017}
$query = ['cars.year' => $years[0]];
//{ $push: { "cars.$.data": { "car":"chevy", "color":"black"} }}
$update = ['$push'=> ['cars.$.data'=>['car' => $car, 'color' => $color]]];
try {
$bulkWriteManager->update($query, $update); // Update Document
echo 1;
} catch(MongoCursorException $e) {
/* handle the exception */
echo 0;
}
$manager->executeBulkWrite('dbName.carsCol', $bulkWriteManager); // Going to DB and Collection
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
}
?>
For accessing data by year you can run below query.
Use query positional $operator to find the array index using the query part and reference that value in projection part.
db.collection.find({"cars.year":2017}, {"cars.$.data":1});
Alternative Solution :
This will take care of everything as just inserts
You are better off saving each car entry in its own document.
{ "year" : 2017, "car" : "Motorolla", "color" : "blue" }
{ "year" : 2016, "car" : "Toyota", "color" : "green" }
{ "year" : 2015, "car" : "Corolla", "color" : "black" }
For each entry you can use:
db.collection.insert({"year":2017, "car":"Motorolla", "color":"blue"});
PHP Code:
//{"car":"chevy", "color":"black", year: 2017}
$insert = ['car' => $car, 'color' => $color, 'year' => $years[0]];
try {
$bulkWriteManager - > insert($insert); // Inserting Document
echo 1;
} catch (MongoCursorException $e) {
/* handle the exception */
echo 0;
}
For access data by year you can use
db.collection.find({"year":2017});
Updated PHP code:
<?php
try {
$cars = ['Motorolla','Toyota', 'Corolla'] ;
$colors = ['blue', 'green', 'black'];
$years = [2017, 2016, 2015];
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulkWriteManager = new MongoDB\Driver\BulkWrite;
$query1 =["year" => $years[0]];
$query2 =["year" => $years[1]];
$query3 =["year" => $years[2]];
$update1 = ['$set' => ['car' => $cars[0], 'color' => $colors[0]]];
$update2 = ['$set' => ['car' => $cars[1], 'color' => $colors[1]]];
$update3 = ['$set' => ['car' => $cars[2], 'color' => $colors[2]]];
try {
$bulkWriteManager->update($query1, $update1, ["upsert" => true]);
$bulkWriteManager->update($query2, $update2, ["upsert" => true]);
$bulkWriteManager->update($query3, $update3, ["upsert" => true]);
echo 1;
} catch(MongoCursorException $e) {
/* handle the exception */
echo 0;
}
$manager->executeBulkWrite('dbName.carsCol', $bulkWriteManager); // Going to DB and Collection
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
}
?>
You can perform complex queries using aggregation pipeline and you can add index to make your response quicker.
Observations:
First Solution : Harder to update/insert data, but keeps everything together so easier to read data.
Second Solution :
Cleaner and simpler to do CRUD operations on documents and use aggregation pipeline to preform complex queries.
Try to change
$document = ['_id' => new MongoDB\BSON\ObjectID, '$years[0]' => $car, '$years[1]' => $color];
to something like:
$document = ['_id' => new \MongoDB\BSON\ObjectID, $years[0] => ['car' => $car, 'color' => $color]];
it gives such result in mongo:
{ "_id" : ObjectId("58a936ecfc11985f525a4582"), "2017" : { "car" : "Motorolla", "color" : "blue" }
If data about all cars must be in one document, you need to combine data fitst:
$cars = [
'2017' => [
'car' => 'Motorolla',
'color' => 'blue'
],
'2016' => [
'car' => 'Toyota',
'color' => 'green'
],
'2015' => [
'car' => 'Corolla',
'color' => 'black'
]
];
and than
$document = ['_id' => new \MongoDB\BSON\ObjectID, 'cars' => $cars];
It gives mongo document like:
{ "_id" : ObjectId("58aabc0cfc11980f57611832"), "cars" : { "2017" : { "car" : "Motorolla", "color" : "blue" }, "2016" : { "car" : "Toyota", "color" : "green" }, "2015" : { "car" : "Corolla", "color" : "black" } } }

PDO There is no active transaction

One of my class files has been spitting out the "There is no active transaction" warning when creating some records. It is the only one doing it and I can't figure out why because all my queries are executing successfully.
My php_errors log has given me zero insight to the issue, nor have any of the other related questions provided any solutions.
try {
App::$DB->beginTransaction();
$rQuery = App::$DB->prepare("INSERT INTO `Cervidae` (`".implode('`, `',array_keys($aSQL)) ."`) VALUES (".implode(",",$aPlaceholders).")");
$rQuery->execute(array_values($aSQL));
$this->_Cervid_ID = App::$DB->lastInsertId();
if (is_array($aData["Treatments"])) {
foreach ($aData["Treatments"] as $sTreatmentName => $sTreatmentData) {
$oTreatmentToCervid = new TreatmentToCervid(array("Treatment_ID" => $sTreatmentData["Treatment_ID"], "Cervid_ID" => $this->_Cervid_ID, "CreatedBy" => $aSQL["CreatedBy"], "UpdatedBy" => $aSQL["UpdatedBy"], "Dose" => $sTreatmentData["TreatmentDose"]), "NEW");
}
}
$oHerdSize = App::getFlat(self::get(array("COUNT(Cervidae.Cervid_ID) AS HerdSize"),array("Cervidae.Herd_ID = $nHerdID","Cervidae.IsActive = 1")));
$rQuery = App::$DB->prepare("UPDATE `Herds` SET `HerdSize` = ".$oHerdSize->HerdSize." WHERE `Herd_ID` = ".$nHerdID);
$rQuery->execute();
App::$DB->commit();
$this->__construct($this->_Cervid_ID, 'ID');
}
catch (Exception $e) {
App::$DB->rollBack();
throw new Exception($e->getMessage());
}

MongoDB MapReduce returning null values in PHP (but works in Javascript)

I am trying to make a Map-Reduce command in PHP with exactly the same functions as in pure JavaScript and surprisingly the result is not the same. I have null values in PHP :-(
I have an "employees" collection, for each employee there is a list of "departments" to which he/she belongs.
So the Javascript map-reduce code (which works) to get the number of employees by department will be:
map = function() {
if (!this.department) {
return;
}
for (i in this.department) {
emit(this.department[i], 1);
};
};
reduce = function(key, values) {
var total = 0;
for (i in values) {
total += values[i];
};
return total;
};
retorno = db.runCommand({
"mapreduce": "employees",
"map": map,
"reduce": reduce,
"out": "employees_by_department"
});
if (retorno.ok != 1) {
print(retorno.errmsg);
};
resultado = db.employees_by_department.find();
while ( resultado.hasNext() ) {
printjson( resultado.next() );
}
And the equivalent PHP code (with null values) will be:
<?php
try {
$connection = new MongoClient( "mongodb://localhost" );
$db = $connection->selectDB("employees");
} catch (Exception $e) {
printf("Error: %s: %s\n", "Error al conectarse a MongoDB: ", $e->getMessage());
die();
}
$map = new MongoCode("function() {
if (!this.department) {
return;
}
for (i in this.department) {
emit(this.department[i], 1);
};
};");
$reduce = new MongoCode("reduce = function(key, values) {
var total = 0;
for (i in values) {
total += values[i];
};
return total;
};");
$retorno = $db->command(array(
"mapreduce" => "employees",
"map" => $map,
"reduce" => $reduce,
"out" => "employees_by_department_php"
));
if ($retorno["ok"] =! 1) {
print($retorno["errmsg"]);
}
else {
$resultado = $db->selectCollection("employees_by_department_php")->find();
foreach($resultado as $dep) {
printf("_id: \"%s\", value: %d\n", $dep["_id"], $dep["value"]);
}
}
?>
Any ideas?
UUpppss!! Solved! The problem was a typo error (a copy-paste problem) :-|
In PHP the first line of the reduce function, where it was
$reduce = new MongoCode("reduce = function(key, values) {
should be
$reduce = new MongoCode("function(key, values) {

PHP Arrays - How to use Multiple variables in array

I have a product import code for Magento that assigns inventory (qty) to a warehouse location (stock_id). The information is passed in an array however my working knowledge of arrays isn't that flash so I'm sure I'm not doing this correctly.
The import is currently done like this however I'm sure it's not the most efficient as I'm saving the product twice.
This will assign a qty of 100 to location 1 (stock_id 1), save the product, then assign a qty of 200 to location 2 (stock_id 2) and then save the product again.
$stocksData = $product->getStocksData();
if (!$stockData) {
$stockData = array();
}
$stockData['stock_id'] = 1;
$stockData['qty'] = 100;
$stocksData[$stockId] = $stockData;
$product->setStocksData($stocksData);
$product->setCreatedAt(strtotime('now'));
try {
$product->save();
echo "Successful";
}
catch (Exception $ex) {
echo 'There was an error :<br/>' .$ex;
}
$stocksData = $product->getStocksData();
if (!$stockData) {
$stockData = array();
}
$stockData['stock_id'] = 2;
$stockData['qty'] = 200;
$stocksData[$stockId] = $stockData;
$product->setStocksData($stocksData);
$product->setCreatedAt(strtotime('now'));
try {
$product->save();
echo "Successful";
}
catch (Exception $ex) {
echo 'There was an error :<br/>' .$ex;
}
What I'm trying to achieve is to set all of the values in the array and save once as this will take a lot of load off the script.
I've been playing around with stuff like this, however haven't got anywhere and usually end up with errors:
$stocksData = $product->getStocksData();
if (!$stockData) {
$stockData = array();
}
$stockData = array(
[$stockData['stock_id'] = 1] => $stockData['qty'] = 100,
[$stockData['stock_id'] = 2] => $stockData['qty'] = 200
);
$stocksData[$stockId] = $stockData;
$product->setStocksData($stocksData);
I'm assuming it's possible to have all of this information in one array but I'm just not sure how.
There are a lot of ways to initialize an array in php.
$stocksData = array(
'key' => 'value',
'myarr' => array(
'nested' => 'array',
1,
),
'id_copy' => $stocksData['id'],
'qty' => $stocksData['stock_id'] == 1 ? 100 : 200,
);
For a full explanation of array syntax, check out php's Array documentation. Also note my usage of the ternary operator. You can get around using this syntax by saying something like:
if ($stocksData['id'] == 1) {
$stocksData['qty'] = 100;
}
else {
$stocksData['qty'] = 200;
}
Edit:
For your specific use case of combining the requests, take a look below:
$stocksData = $product->getStocksData();
$stocksData[1] = array(
'stock_id' => 1,
'qty' => 100,
);
$stocksData[2] = array(
'stock_id' => 2,
'qty' => 200,
);
$product->setStocksData($stocksData);

Categories