PHP MongoDB library findOne returns nothing - php

I'm trying to return a single document from the database by it's ID.
This is what I have right now.
$id = "5a30ff2c3afc720394000ac2";
$collection = (new \MongoDB\Client(DB_HOST))->DB->posts;
$post = $collection->findOne(['_id' => $id]);
findOne() returns nothing while find() seems to be working. MongoDB documentations mentions that it would not return anything if no document were to be found. However, the document does seem to be in my database.
I have also tried PHP MongoDB documentation example.
$post = $collection->findOne(['_id' => new \MongoId($id)]);
This returns a no class found error.

Mongo by default stores _id as Object
Try this
$collection->findOne(['_id'=> new \MongoDB\BSON\ObjectId("$mongoId")]);
You are using MongoDB driver, but using Mongo driver object.

Related

How to make aggregation, using PHP MongoDB driver

I use this MongoDb driver in my application. I like it, because it works well. I can run simple select and insert statements, like:
$em = new MongoDB\Driver\Manager("mongodb://localhost:27017/testdb");
$query = new Query(['name' => 'John']);
$res = $em->executeQuery('users', $query);
But the problem is, I can not find even a single example on making aggregations. PHP documentation does not say a word about this. While, MongoDb documentation seems to use another library:
$collection = (new MongoDB\Client)->test->restaurants;
$cursor = $collection->find([
'name' => new MongoDB\BSON\Regex('^' . preg_quote('(Library)')),
]);
It seems like an example from another library, because MongoDb driver does not have this MongoDB\Client class. There is such a class, but in a deprecated library. So, what is the right way to make aggregations in PHP, using modern MongoDb driver?
This extension provides a minimal API for core driver functionality: commands, queries, writes, connection management, and BSON serialization.
https://www.php.net/manual/en/set.mongodb.php
To execute aggregate command, use MongoDB\Driver\Command
{
aggregate: "<collection>" || 1,
pipeline: [ <stage>, <...> ],
explain: <boolean>,
allowDiskUse: <boolean>,
cursor: <document>,
maxTimeMS: <int>,
bypassDocumentValidation: <boolean>,
readConcern: <document>,
collation: <document>,
hint: <string or document>,
comment: <string>,
writeConcern: <document>
}
https://docs.mongodb.com/manual/reference/command/aggregate/#syntax

How to create MongoDB views in PHP using MongoDB\Client() library?

I'm using following:
PHP 7.2
MongoDB 3.4
Pecl 1.5.2
I'm working on a Laravel project. It uses MongoDB as database. I have few collections on which I have to create Mongo Views using Laravel migration. I was wondering whether its possible to create Mongodb Views using PHP. Currently I have a work around. I have created a JavaScript file which has MongoDB db.createView() query in it. It also takes view name and collection name as parameters. Following is my work around. $db has database name, $view has view name, $collection has collection name and $script has the path to the JavaScript file. This code I'm writing in migration class's up() method.
$cmd = "mongo $db --eval \"var view='$view', collection='$collection'\" $script";
exec($cmd);
In my Javascript file, I have code something like following
db.createView(view, collection, <aggregate query>);
So as everyone can see, I'm running terminal command from PHP to make views. So is there any PHP function in mongo library to make mongo views?
If you're using mongo with Laravel, I'm going to assume you're using jenssegers/mongodb to use it with Eloquent.
So, let's assume you have your mongo database set up as your 'mongodb' database connection. You need the MongoDB\Database for your database. You can get this with:
$mongo = app('db')->connection('mongodb')->getMongoDB();
Of course, if you're not using jenssegers/mongodb, you can still do the same thing with mongodb/mongodb as well.
$mongo = (new MongoDB\Client)->selectDatabase($db);
This has a method called command (see https://docs.mongodb.com/php-library/current/reference/method/MongoDBDatabase-command/), which corresponds to the db.runCommand method from the mongo cli. db.createView calls that method (see https://docs.mongodb.com/manual/reference/method/db.createView/#db.createView)
So, you can use $mongo->command to create the view like this:
$mongo->command([
'create' => $view,
'viewOn' => $collection,
'pipeline' => $aggregateQuery,
'collation' => ['locale' => 'en'],
]);
You can use this library mongoPhpLibrary
This will make your work easy

Cannot get all entities under a kind in google datastore (using PHP)

I am new to google datastore, and I cannot get all entities under a kind. Here is my code.
use Google\Cloud\Datastore\DatastoreClient;
use Google\Cloud\Datastore\Query\Query;
function get_datastore_client(){
# Your Google Cloud Platform project ID
$projectId = 'my-project-id';
# Instantiates a client
$datastore = new DatastoreClient([
'projectId' => $projectId
]);
return $datastore;
}
function get_athlete_list(DatastoreClient $datastore){
$transaction = $datastore->transaction();
$query = $datastore->query()
->kind('Athlete')
->order('country');
$result = $transaction->runQuery($query);
$transaction->commit();
return $result;
}
$datastore = get_datastore_client();
$all_athletes = get_athlete_list($datastore);
And when I ran this, I got empty result. Please help me to find out what is wrong.
Update:
I have tried using datastore instead of transaction and it didn't work, too. Function without transaction is below.
function get_athlete_list(DatastoreClient $datastore){
$query = $datastore->query()
->kind('Athlete')
->order('country');
$result = $datastore->runQuery($query);
return $result;
}
And the strange thing is I can get one entity by its ID, function is below. I just cannot get all entities.
(This function works.)
function lookup_athlete(DatastoreClient $datastore, $athlete_id){
$transaction = $datastore->transaction();
$kind = 'Athlete';
$athleteKey = $datastore->key($kind, $athlete_id);
$athlete = $transaction->lookup($athleteKey);
if(empty($athlete)){
$transaction->rollback();
}
return $athlete;
}
So I think that maybe a setting issue, but I just cannot find out. I ran this in a compute engine instance and I have an APP engine instance runnning, according to this document, Accessing the Cloud Datastore API from a Compute Engine instance.
Update with solution:
After hours of research, I found that in datastore library, "yield" is used instead of "return". This means the returned variable is just a generator object. And I didn't use the generator, so I cannot get the generated data. And that is why I got the issue. BTW, all my code is fine. :)
Thank you for all the replies.
I'm not a PHP developer, but looks like you are using a transaction to load all records from an entity. This is not permitted because queries inside a transaction should be ancestor queries. My guess is that you are probably getting an exception/error indicating the same, but is being swallowed somewhere. If all you need to read the entities, you don't need a transaction, just use the datastore.

Mongo-PHP - MongoCursor exception with MongoDB PHP Driver v1.6

I'm having troubles with PHP MongoCursor since I upgraded to Mongo PHP Driver from 1.5.8 to 1.6.0
The following code works well with version 1.5.8, but crashes with version 1.6
PHP version is 5.5.21., Apache version is Apache/2.4.10 (Ubuntu)
$mongoClient = new \MongoClient($serverUrl, ['readPreference'=>\MongoClient::RP_NEAREST]);
$database = $mongoClient->selectDB($dbName);
$collection = $database->selectCollection($collectionName);
// count() works fine and returns the right nb on documents
echo '<br/>count returned '.$collection->count();
// find() exectues with no error...
$cursor = $collection->find();
$documents = [];
// ...and hasNext() crashes with the Excetion below
while($cursor->hasNext()){$documents[] = $cursor->getNext();}
return $documents;
And so the hasNext() call crashes with this message :
CRITICAL: MongoException: The MongoCursor object has not been correctly initialized by its constructor (uncaught exception)...
Am I doing something wrong ?
Thanks for you help !
This may be related to a bug that was introduced in 1.6.0 regarding iteration with hasNext() and getNext(): PHP-1382. A fix has since been merged to the v1.6 branch and should be released later this week as 1.6.1.
That said, the bug regarding hasNext() was actually that the last document in the result set would be missed while iterating. If I run your original script against 1.6.0, the array contains a null value as its last element. With the fix in place, the array will contain all documents as is expected. I cannot reproduce the exception you're seeing with either version.
That exception is actually thrown from an internal checks on the C data structures, to ensure that the cursor object is properly associated with a MongoClient and socket connection. See the MONGO_CHECK_INITIALIZED() macro calls in this file. Most all of the cursor methods check that a MongoClient is associated, but hasNext() is unique in that it also checks for the socket object (I believe other methods just assume a cursor with a MongoClient also has a socket). If that exception is truly reproducible for you and you're willing to do some debugging with the extension, I'd be very interested to know which of the two checks is throwing the error.
As a side note, you should also be specifying the "replicaSet" option when constructing MongoClient. This should have the replica set name, which ensures that the driver can properly ignore connections to hosts that are not a member of the intended replica set.
I just encountered the same issue; I refactored my code to use the cursor iterator instead, ie:
foreach( $cursor as $doc ) {
$documents[] = $doc;
}
I was looking for a code example of how to implement a tailable cursor and found this question. The following code is a simple example of a tailable cursor (via the $cursor variable) which you provide on a capped mongodb collection.
$cursor->tailable(true);
$cursor->awaitData(true);
while (true) {
if ($cursor->hasNext()) {
var_dump($cursor->getNext());
} else {
if ($cursor->dead()) {
break;
}
}
}

Call stored procedure/function with PHP in Mongo DB sharded cluster

I am using MongoDB 2.6 with two shard clusters config.
I want to call a function dataStats() that I create and store in MongoDB. This is my PHP script:
$client = new Mongo();
$db = $client->mydata;
$db->system->js->save(array("_id"=>"dataStats",
"value"=>new MongoCode("function() { ... }")));
$db->execute("dataStats()");
This code gives me this error:
'err' => 'Error: can\'t use sharded collection from db.eval',
'code' => 16722
The reason is $db->execute method is using Mongo db.eval command which is not supported with sharded collections. Is there a workaround for this issue? How can we call a stored procedure in sharded MongoDB from PHP?
There's no workaround. db.eval doesn't work with sharded collections. You should avoid using it if at all possible, anyway.

Categories