I'm trying to access the MongoDB profiler in PHP with the same query I would use in the mongo client:
$db = $mongo->selectDB('myapp_db');
$array = $db->execute('return db.system.profile.find();');
echo '<pre>' . print_r($array, true);
But I get this:
Array
(
[retval] => Array
(
[value] => DBQuery: myapp_db.system.profile -> undefined
)
[ok] => 1
)
Profiling is enabled and works fine in the client.
Method MongoDB::setProfilingLevel — Sets this database's profiling level
<?php
$dbname = 'students';
$mongo = (new MongoClient());
$db = $mongo->$dbname;
# 0 (off), 1 (queries > 100ms), and 2 (all queries)
$db->setProfilingLevel(2);
# …
# Some queries
# …
$response = $db->system->profile->find();
foreach ($response as $query) {
print_r($query);
}
Also:
Method MongoDB::getProfilingLevel — Gets this database's profiling level
Method MongoCursor::explain — Return an explanation of the query, often useful for optimization and debugging
There's no need to execute a query in JavaScript, which blocks the server/database, when you can use PHP itself:
$mongo = new MongoClient();
// Alternatively, use selectCollection from $mongo->myapp_db
$collection = $mongo->selectCollection('myapp_db', 'system.profile');
foreach ($collection->find() as $document) {
print_r($document);
}
This makes more efficient use of memory, since you can iterate through results instead of fetching the entire MongoDB::execute() response in a single array.
Additionally, your original code returns the cursor (a DBQuery object) from JavaScript. To ensure compatibility with other drivers, you should invoke cursor.toArray() before returning. This is discussed in Sammaye's answer to a similar question here.
Related
I have a MongoDB server with a collection counting hundreds of thousands of documents.
I need to get only the number of documents matching the query filter condition using MongoDB\Driver in PHP.
In mongo-shell I would simply do the following:
db.samples.find({"location": {$geoWithin: {$geometry: ...reference_polygon... }}}).length
The below query in PHP would return a cursor with the full list of the documents (could be thousands of docs) which I don't need, I'm only looking for the number of the samples within a specified polygon:
$query = new MongoDB\Driver\Query(
["location" => ['$geoWithin' => ['$geometry' => $reference_polygon]]],
[]
);
$cursor = $dbm->executeQuery("test.samples", $query);
Even reducing projection to return a single field as _id would significantly increase the calculation time.
Is there any way to get just a scalar number of documents and avoid loading cursor results and then counting it like count($cursor->toArray())?
MongoDB Server: 4.4.1
PHP version: 7.4
OS: Ubuntu 20.04 LTS
So, finally, I found a way to do it using MongoDB\Driver\Command.
The code is below, would someone have a better proposal, please feel free to comment.
$database_name = "test";
$collection_name = "samples";
$query = new MongoDB\Driver\Query(
["location" => ['$geoWithin' => ['$geometry' => $reference_polygon]]],
[]
);
$dbc = new MongoDB\Driver\Command(
['count' => $collection_name, "query" => (object)$query]
);
$cursor = $dbm->executeCommand($database_name, $dbc);
$n = (isset($cursor->toArray()[0]->n)) ? $cursor->toArray()[0]->n : 0;
Here is the error Log
Fatal error: Cannot use object of type PDO as array in /Applications/XAMPP/xamppfiles/htdocs/php/blog/single.php on line 13
Here is 13 number line
$post = DB\query('SELECT * FROM posts WHERE id = :id LIMIT 1', array('id' => $_GET['id']), $conn [0] );
i got this error when i try to get post title.
<?= $post['title'];?>
Full Code
<?php
require 'functions.php';
use blog\DB;
// Connect to the DB
$conn = DB\connect($config);
if( !$conn ) die('Problem Connecting to the DB');
// Fetch all the posts
$post = DB\query('SELECT * FROM posts WHERE id = :id LIMIT 1', array('id' => $_GET['id']), $conn [0] );
// Filter throgh and display in the view
$view_path = 'views/single.view.php';
include 'views/layout.php';
Instead of $conn[0], Try using $conn.
For future issues, always remember you can output the datatypes, content, and structures of variables in php.
Use the following to output the content in human readable format.
echo "<pre>";
print_r($variable);
echo "</pre>";
die();
Use the following to output the content with datatype and extra info
echo "<pre>";
var_dump($this);
echo "</pre>";
die();
Remember functions like gettype() etc.
Also based on your further comments, I'd recommend that you first grab a book or an online course of the language.
About your next error, remember that in php the variable needs to be defined before you can call/use it.
So on the line, where you care calling $post['title']; remember to first make sure that that variable is defined and has the index that you intend to call. Also use the above snippets to verify and you should be writing the handling code if that index is not set.
something like..
if(isset($post) && !empty($post) && isset($post['title'])) {
....
I have the following code which executes a piece of code on the MongoDb's side:
$mongoCode = new MongoCode('/* Some JS code */');
$db->execute($mongoCode, array(
'socketTimeoutMS' => 1000000,
));
As you see I have tried to set timeout for the code's execution by setting the socketTimeoutMS value in second parameter of execute() function. But it does not work. Documentations in PHP website indicate that the second parameter of execute() command is sent to code as arguments.
How can I set timeout for MongoDB::execute()? Please note that I am using version 1.5 of MongoDB driver for php and MongoCursor::$timeout is deprecated and does not work anymore.
You can set the socketTimeoutMS on MongoClient:
$mongo = new MongoClient("mongodb://localhost:27017",
array(
"socketTimeoutMS" => 100000
)
);
The args parameters for the execute method are passed to the code not to the driver.
You can also set a timeout just when executing the command:
$result = $mongo->dbname->command(
['eval' => $code],
['socketTimeoutMS' => 1]
);
Alternatively, if you're not executing commands, you can set the timeout on the cursor:
$cursor = $collection->find([]);
$cursor->timeout(10000);
This will obviously not work on the execute command, because that command doesn't return a cursor.
You want the MongoDB::command implementation for this which actually accepts the argument:
<?php
$mongo = new MongoClient('mongodb://192.168.2.3/test');
$db = $mongo->test;
$code = new MongoCode( 'sleep(100); return "hello";' );
try {
$res = $db->command(
array("eval" => $code),
array( 'socketTimeoutMS' => 1 )
);
echo var_dump( $res );
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
?>
Note that even though the exception will be thrown for the timeout, this does not not actually stop the code running on the server. That you would have to handle yourself.
Look into the killOp() and currentOP() methods, with their usage and implementation for a way to control and processes left running after your timeout expires on this operation.
Really try to look for other approaches rather than executing JavaScript on the server like this.
how do i use getLastError() within php to check if my save method is inserting to mongo?
i set up my db as follows:
$this->databaseEngine = $app['mongo'];
$this->db = $this->databaseEngine->dbname;
$this->collection = $this->db->collectionname;
my insert query then looks like this:
$query = array(
'fieldname' => $fieldname
);
$this->collection->insert($query);
I want to then use getLastError() to check whether it is inserting correctly, and if not why. but im not sure how to implement it.
do i use after the insert:
$this->collection->getLastError("what goes here?");
cheers.
Update
i eventually used this to get the last error:
echo '<pre>' . print_r($this->databaseEngine->lastError(), true) . '</pre>';
Sammaye's way works just as well, see below.
$this->collection->getLastError("what goes here?");
Nothing goes there, the return of the getLastError is the last error from MongoDB ( http://www.php.net/manual/en/mongodb.lasterror.php ). Also it is used on the MongoDB class (atm).
You don't have to use it like that, instead you can do:
$this->collection->insert($query, ARRAY('safe' => TRUE));
This will return an array from the function detailing whether or not it actually inserted. The details of the array can be found by reading this page:
http://www.php.net/manual/en/mongocollection.insert.php
MongoDB + PHP: How do you query the size of a document stored in a mongodb object? The document limit, at the time of this writing (recently raised from 4MB), is 16MB.
How can I query the size of a Document using the ObjectId?
Object.bsonsize(document) is the function you're after. I'm reading this thread and finding a few suggestions about how to do it in php. The easiest is probably to query for the document object and run strlen on the bson_encode'd object giving you the size in bytes.
$byteSize = strlen( bson_encode( $yourDocument ) );
If you're wanting to do this check on a lot of documents, say in a loop, without reading back every document you'll need to run a command execute (Mardix had posted this little function to do just that - note: it could easily be rewritten a little better to avoid the hardcoded and global variables):
$DBName = "MyDBName";
$MongoDB = new MongoDB(new Mongo(),$DBName);
function documentSize(Array $Criteria){
global $MongoDB;
$collectionName = "MyCollection";
$jsonCriteria = json_encode($Criteria);
$code = "function(){
return Object.bsonsize(db.{$collectionName}.findOne({$jsonCriteria}))
}";
$resp = $MongoDB->execute($code);
return $resp["retval"];
}
PHP example where $id is the document id
$myDocSize = documentSize(array("_id"=>$id));