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

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