How to make aggregation, using PHP MongoDB driver - php

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

Related

How to explain mongodb query plan with PHP MongoDB driver

The current PHP MongoDB client doesn't include an explain() feature in the query builder. How the explain information could be retrieved for the query below?
use MongoDB\Client;
$client = new Client($mongoUri);
$database = $client->selectDatabase('someDB');
$collection = $database->selectCollection('collectionName');
$results = $collection->find(['key' => 'value'], ['sort' => ['key2' => -1]]);
MongoDB client: https://www.php.net/manual/en/class.mongodb.php
MongoDB::command could be a way to the solution. https://www.php.net/manual/en/mongodb.command.php
Note! There is a deprecated mongodb client that has this feature.
One way of doing it:
Get the find command that the driver sends to the database for your query. It would look like this. Generally these can be obtained from command monitoring, hopefully this works.
Send an explain command giving the find command as the argument using the driver-provided facility to send arbitrary commands to the database. Or, use mongo shell for this part.

How can I integrate elasticsearch to mysql using php

I was working on a project which is required to use elasticsearch. I followed the guide: https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
It works perfectly for me:
require 'vendor/autoload.php';
use Elasticsearch\ClientBuilder;
$hosts = [
'myhost'
];
$client = ClientBuilder::create() // Instantiate a new ClientBuilder
->setHosts($hosts) // Set the hosts
->build();
$params = [
'index' => 'php-demo-index',
'type' => 'doc',
'id' => 'my_id',
'body' => ['testField' => 'abc']
];
$response = $client->index($params);
print_r($response);
Now, that's only a basic thing. Now, what I want is to integrate this with Mysql i.e. as I update or insert into my table in database, it get indexed automatically in elasticsearch.
I know, we have Logstash that can query db constantly after a given interval and index into elasticsearch. But, I want indexing to be happened automatically after insertion into db using PHP without logstash.
I know such a library in (nodeJs+mongodb) ie. mongoosastics: https://www.npmjs.com/package/mongoosastic. Is there any library available in php which can do such a task automatically. Please provide me the sample code, if you know one.
There is indeed libraries to automate this task. However it generally requires the use of an ORM like Doctrine in order gracefully hook in to your database implementation. If you are able to use the Symfony framework in your project there is a library called FOSElasticaBundle which keeps your indices in sync with your database operations.

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

MapReduce with PHP and MongoDB

I'm fairly new to Mongo and I have what I thought was a simple question. How do I do MapReduce with PHP and the non legacy MongoDB driver http://php.net/manual/en/set.mongodb.php or the higher level package mongodb/mongodb found at https://packagist.org/packages/mongodb/mongodb?
Every example I've seen seems to use the legacy driver (http://php.net/manual/en/book.mongo.php). They all use the MongoCode object, which doesn't exist in mongodb.php. It exists in mongo.php (the legacy driver). When I try and use it, it will say that "Class 'MongoCode' not found".
My code looks something like:
$function = "function() { emit(this); }";
$map = new \MongoCode($function);
$command = $db->command([
"mapreduce" => "db.archiveData",
"map" => $map,
"query" => $query,
"out" => "data"
]);
To make things more confusing, when I look at the source at https://github.com/mongodb/mongo-php-library, there is a unit test for MapReduce (https://github.com/mongodb/mongo-php-library/blob/4dc36f6231df133a57ff0dc5a0123945133d25ba/tests/Operation/MapReduceFunctionalTest.php). But it uses the MongoDB\Operation\MapReduce, which doesn't seem to exist in the 1.1 version of mongodb/mongodb.
I thought maybe I would call it on the server using JavaScript. But when I look at http://php.net/manual/en/mongodb.execute.php, it says it "is deprecated in MongoDB 3.0+". So that doesn't feel like something I should use.
So is it that:
MapReduce is not supported with mongodb/mongodb. Or maybe it is not supported yet, but will be?
I have to use the legacy driver for MapReduce?
I have to figure out a way to call db.collection.mapReduce via JavaScript on the server?
I have to use the Aggregation Pipeline (https://docs.mongodb.com/manual/aggregation/) to do map reduce type of actions? But that feels much more limited.
What am I missing?
So I now have clarity on where things are at.
MapReduce will be officially supported in 1.2.0 of PHPLib (https://jira.mongodb.org/browse/PHPLIB-53)
Until then, there is a completely usable workaround by using the command object as per https://docs.mongodb.com/php-library/current/upgrade/#mapreduce-command-helper
Example is here as well:
$database = (new MongoDB\Client)->selectDatabase('db_name');
$cursor = $database->command([
'mapReduce' => 'collection_name',
'map' => new MongoDB\BSON\Javascript('...'),
'reduce' => new MongoDB\BSON\Javascript('...'),
'out' => 'output_collection_name',
]);
$resultDocument = $cursor->toArray()[0];
You can also use MapReduce via Doctrine (http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/map-reduce.html), but that is using legacy and a shim. So probably not a good choice for a new project.

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