Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Plaing with Neo4j -[:USING]-> PHP

Plaing with Neo4j -[:USING]-> PHP

Slides from my talk at FrOSCon 2014

Avatar for Frank Neff

Frank Neff

August 23, 2014
Tweet

More Decks by Frank Neff

Other Decks in Programming

Transcript

  1. About me Frank Neff ▪ Software Engineer @ YMC AG

    ▪ Living in Zurich, Switzerland ▪ Coding PHP and Java ▪ Student ▪ Open Source Enthusiast ▪ UAV Drone Pilot ▪ Hobby Photographer ▪ frankneff.ch ▪ ymc.ch
  2. We're entering a new world in which data may be

    more important than software - Tim O'Reilly
  3. ▪ Users can be friends with other Users ▪ Users

    can follow other Users ▪ Users can write Posts ▪ Users can like other Posts ▪ Users can share other Posts Let’s build a social network
  4. ▪ Graph -[:RECORDS_DATA_IN]-> Nodes ▪ Nodes -[:CAN_HAVE]-> Properties ▪ Nodes

    -[:ARE_CONNECTED_BY]-> Relations ▪ Relations -[:CAN_HAVE]-> Properties
  5. ▪ Graph model for data representation ▪ Reliable, with full

    ACID transactions ▪ Scalable, up to several billion nodes/relationships/properties ▪ Cypher, a human readable query language ▪ REST interface or Java API Features
  6. 1 CREATE 2 (a:Person { 3 name:'Pascal', title:'Senior Software Engineer',

    4 company: 'YMC' 5 }), 6 (b:Person { 7 name:'Manuel', title:'Software Engineer', 8 company: 'YMC' 9 }), 10 (c:Person { 11 name:'Simon', title:'Head of Web Solutions', 12 company: 'YMC' 13 }) 14 RETURN a,b,c Create some more nodes
  7. Neo4j handles relations as objects, holding: ▪ source (Node) ▪

    target (Node) ▪ properties (Key-Value Pairs)
  8. 1 MATCH 2 (s:`Person` { name:'Frank' }), 3 (t:`Person` {

    name:'Manuel' }) 4 CREATE (s)-[r:WORKS_WITH]->(t) 5 RETURN s,t,r Creating a relation
  9. 1 MATCH (me:Person) 2 WHERE me.name = 'Frank' 3 CREATE

    (ymc:Company { name:'YMC', business:'IT' }) 4 CREATE (me)-[relation:WORKS_AT]->(ymc) 5 RETURN me,ymc,relation; Multiple creates
  10. 1 MATCH 2 (me:Person {name:'Frank'}), 3 (ymc:Company { name:'YMC'}) 4

    CREATE (me)-[worksat:WORKS_AT {since:1291186800}]->(ymc) 5 RETURN me,worksat,ymc; Relationship properties
  11. ▪ (Almost) all features available ▪ Works out of the

    box ▪ JSON ▪ Fast ▪ Transactional HTTP endpoint to run cypher queries
  12. POST http://localhost:7474/db/data/transaction Accept: application/json; charset=UTF-8 Content-Type: application/json { "statements" :

    [ { "statement" : "CREATE (n {props}) RETURN n", "parameters" : { "props" : { "name" : "My Node" } } } ] } Creating a node Request
  13. 200 OK Content-Type: application/json { "results" : [ { "columns"

    : [ "id(n)" ], "data" : [ { "row" : [ { "name" : "My Node" } ] } ] } ], "errors" : [ ] } Creating a node Response
  14. Executing Cypher queries POST http://localhost:7474/db/data/cypher Accept: application/json; charset=UTF-8 Content-Type: application/json

    { "query" : "MATCH (x {name: 'I'})-[r]->(n) RETURN type(r), n.name, n.age", "params" : { } } Executing Cypher queries Request
  15. Executing Cypher queries Executing Cypher queries 200 OK Content-Type: application/json

    { "columns" : [ "type(r)", "n.name", "n.age" ], "data" : [ [ "know", "him", 25 ], [ "know", "you", null ] ] } Response
  16. PHP Wrapper for the Neo4j graph database REST interface everyman/neo4jphp

    ▪ Written in PHP ▪ Abstracts cURL requests behind a wrapper ▪ Installation using GitHub / Composer ▪ Easy to use ▪ Implemented in many other projects ▪ github.com/jadell/neo4jphp
  17. // autoloading require('vendor/autoload.php'); // Connecting to the default port 7474

    on localhost $client = new Everyman\Neo4j\Client(); // create a new node $arthur = $client->makeNode(); $arthur->setProperty('name', 'Frank') ->setProperty('title', 'Software Engineer') ->setProperty('company', 'YMC') ->save(); // get ID from Neo4j $arthurId = $arthur->getId();
  18. Doctrine2-style entity mapper for Neo4j graph database hirevoice/neo4jphp-ogm ▪ Written

    in PHP ▪ Provides entity mapping using annotations ▪ Installation using GitHub / Composer ▪ Similar to Doctrine ORM ▪ Implements doctrine/common ▪ github.com/lphuberdeau/Neo4j-PHP-OGM
  19. namespace Entity; use HireVoice\Neo4j\Annotation as OGM; /** * @OGM\Entity */

    class User { /** * @OGM\Auto */ protected $id; /** * @OGM\Property * @OGM\Index */ protected $fullName; }
  20. ▪ Entity ▪ Auto ▪ Porperty ▪ Index ▪ ManyToOne

    ▪ ManyToMany Available annotations
  21. ▪ Entity ▪ Auto ▪ Porperty ▪ Index ▪ ManyToOne

    ▪ ManyToMany use HireVoice\Neo4j\Annotation as OGM; /** * @OGM\Entity( * repositoryClass="Repo\UserRepository", * labels="Location,City" * ) */ class MyEntityWithCustomRepositoryAndLabels { // definition } Available annotations
  22. ▪ Entity ▪ Auto ▪ Porperty ▪ Index ▪ ManyToOne

    ▪ ManyToMany use HireVoice\Neo4j\Annotation as OGM; class MyEntity { /** * @OGM\Property(format="date") */ protected $releaseDate; } Available annotations
  23. ▪ Entity ▪ Auto ▪ Porperty ▪ Index ▪ ManyToOne

    ▪ ManyToMany use HireVoice\Neo4j\Annotation as OGM; class MyEntity { /** * @OGM\Property * @OGM\Index */ protected $name; } Available annotations
  24. ▪ Entity ▪ Auto ▪ Porperty ▪ Index ▪ ManyToOne

    ▪ ManyToMany use HireVoice\Neo4j\Annotation as OGM; class MyEntity { /** * @OGM\ManyToOne(relation="acts-in") */ protected $mainActor; } Available annotations
  25. $em = // Let's assume the entity manager is initialized

    in $em $repo = $em->getRepository('Entity\\User'); // The repository uses magic functions to search in indexed fields $john = $repo->findOneByFullName('John Doe'); $jane = new User; $jane->setFullName('Jane Doe'); $jane->addFollow($john); $em->persist($jane); $em->flush();
  26. $em = // Let's assume the entity manager is initialized

    in $em $repository = $em->getRepository('Entity\\User'); // Find a User by a specific field $user = $repository->findOneByFullName('superman'); // Returns a User object // Find some users by a specific field $usersFromFrance = $repository->findByCountry('FR'); // Returns a collection // Find one User with more than one criteria $nonActiveWithSuchEmail = $repository->findOneBy(array( 'status' => 'idle', 'email' => '[email protected]') ); // Returns a collection
  27. use HireVoice\Neo4j\Event as Events; class PrePersistListener { public function prePersist(Events\PrePersist

    $event) { $entity = $event->getEntity(); // do your stuff here... } } Create event listener
  28. use \Doctrine\Common\EventManager; $eventManager = new EventManager(); $listener = new PrePersistListener();

    $eventManager->addEventListener( array('prePersist'), // array of all listened events $listener // instance of your event listener ); $entityManager->setEventManager($eventManager); Create event manager
  29. ▪ prePersist - Fires before an entity is persisted ▪

    postPersist - Fires after an entity is persisted ▪ preRelationCreate - Fires before a relation is created ▪ postRelationCreate - Fires after a relation is created ▪ preStmtExecute - Fires before a statement (query) is executed ▪ postStmtExecute - Fires after a statement (query) is executed ▪ preRemove - Fires before an entity is removed ▪ postRemove - Fires after an entity is removed ▪ preRelationRemove - Fires before a relation is removed ▪ postRelationRemove - Fires after a relation is removed Available events
  30. // $list is a collection of User objects $em =

    $this->get('hirevoice.neo4j.entity_manager'); $repo = $em->getRepository('Entity\\User'); $john = $repo->findOneByFullName('John Doe'); $list = $em->createCypherQuery() ->startWithNode('john', $john) ->match('john -[:follow]-> followedBy <-[:follow]- similarInterest') ->match('similarInterest -[:follow]-> potentialMatch') ->end('potentialMatch', 'count(*)') ->order('count(*) DESC') ->limit(10) ->getList(); Collection of entities Follow multiple relations Get em and repo, e.g. from Symfony DIC
  31. ▪ Not recommended for large datasets ◦ Streaming not supported

    ◦ Memory exhaustion ▪ Not feature complete yet ◦ Graph traversals ◦ Relation properties ▪ Small community / few maintainers OGM drawbacks
  32. ▪ Neo4j ◦ ...is the most common graph database ◦

    fast ◦ actively maintained ◦ big community ▪ PHP ◦ ...is the most common scripting language for the web ◦ widely used ◦ big community ◦ other great persistence libs in PHP to learn from Neo4j and PHP
  33. ▪ Join forces ▪ Spread the word ▪ Contribute ◦

    github.com/neoxygen ◦ neo4j.org/develop/php