Symfony permet à l’aide de bundle, de s’implémenter facilement avec MongoDB et Elasticsearch.
Le principe dans l’exemple qui suit, est une application web Symfony qui fonctionne avec une base maître MongoDB.
Cette base MongoDB synchronise régulièrement certaines de ses données dans Elasticsearch qui sera responsable de la recherche.
Symfony interroge ensuite Elasticsearch afin d’obtenir des résultats de recherche, qui lui renvoie les id
des objets MongoDB afin d’aller chercher l’information brute dans la base maître.
Elasticsearch
Installer Elasticsearch à l’aide de la documentation officielle.
Une fois installé et lancé, on peut vérifier si Elasticsearch est bien en route à l’aide de cette commande :
curl -X GET "localhost:9200/"
Résultat :
{
"name" : "_5_5A27",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "RLlBm2geTvqkfesixGotTg",
"version" : {
"number" : "6.5.1",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "8c58350",
"build_date" : "2018-11-16T02:22:42.182257Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
On peut créer un premier index de cette façon :
curl -X PUT "localhost:9200/customer?pretty"
curl -X GET "localhost:9200/_cat/indices?v"
ElasticHQ est un outil intéressant à installer, et gratuit, qui permet de suivre la santé du noeud Elasticsearch et les index qui s’y trouvent.
Une fois récupérer, on lance l’interface avec Python :
python3 manage.py runserver
L’interface sera disponible à l’URL suivant : http://localhost:5000
Pour s’interfacer avec Symfony on va utiliser le bundle FOSElastica ainsi qu’un serializer.
composer require friendsofsymfony/elastica-bundle
composer require jms/serializer-bundle
MongoDB
L’installation se fait depuis le site officiel.
On lance l’instance de MongoDB :
sudo service mongod start
L’outil MongoBooster (désormais NoSQLBooster) est pratique pour visualiser les collections de documents, bien que certaines fonctionnalités deviennent payantes au fil du temps (autocompletion par exemple).
On installe le connecteur PHP :
sudo apt install php-mongodb
Une petite commande est nécessaire pour faire fonctionner Doctrine MongoDB ODM avec PHP7 :
composer config "platform.ext-mongo" "1.6.16" && composer require "alcaeus/mongo-php-adapter"
Puis les librairies qui vont bien :
composer require alcaeus/mongo-php-adapter
composer require doctrine/mongodb-odm
composer require doctrine/mongodb-odm-bundle
Symfony
Un peu de config pour faire fonctionner les bundles (disponible sur les documentations respectives)
app/config/parameters.yml
parameters:
mongodb_server: "mongodb://localhost:27017"
app/config/config.yml
doctrine_mongodb:
connections:
default:
server: "%mongodb_server%"
options: {}
default_database: test
document_managers:
default:
auto_mapping: true
fos_elastica:
default_manager: mongodb
serializer:
serializer: jms_serializer
clients:
default: { host: localhost, port: 9200 }
indexes:
app:
types:
contacts:
properties:
name: ~
lastName: ~
persistence:
# the driver can be orm, mongodb or phpcr
driver: mongodb
model: AppBundle\Document\Contacts
provider: ~
finder: ~
src/AppBundle/Document/Contacts.php
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* @MongoDB\Document
*/
class Contacts
{
/**
* @MongoDB\Id
*/
protected $id;
/**
* @MongoDB\Field(type="string")
*/
protected $name;
/**
* @MongoDB\Field(type="string")
*/
protected $last_name;
On configure Doctrine avec le MongoDB installé en local, idem avec Elasticsearch.
On peut préciser à Elasticsearch d’indexer les contacts (qui est un Document plutôt qu’une Entity), via listener, lancement manuel ou scheduler avec la commande suivante :
php bin/console fos:elastica:populate
Pour créer et lire des documents dans MongoDB, on utilise Doctrine de manière habituelle.
$contact = new Contacts();
$contact
->setName('John')
->setLastName('Doe')
;
$dm = $this->get('doctrine_mongodb')->getManager();
$dm->persist($contact);
$dm->flush();
/*
......
*/
$contacts = $this->get('doctrine_mongodb')
->getRepository(Contacts::class)
->findAll()
;
Une fois Elasticsearch indexé, il est possible de récupérer nos documents via une recherche elastic plus ou moins complexe (voir documentation)
$finder = $this->container->get('fos_elastica.finder.app.contacts');
$results = $finder->find('John');