SlideShare a Scribd company logo
GraphDB in PHP
Alessandro Nadalin   David Funaro




                                    1
Agenda


•Theory
•When to use a graph?
•Why graphDB?
•The graphDB community
•OrientDB
•OrientDB in PHP
•Demo
                         2
Essential (Theory)




                     3
Essential (Theory)



G=
Graph




                         3
Essential (Theory)



G = (V,
             Vertex
Graph




                         3
Essential (Theory)



G = (V,
             Vertex
Graph




               A



                         3
Essential (Theory)



G = (V, E)
             Vertex
Graph




                      Edge
               A



                             3
Essential (Theory)



G = (V, E)
             Vertex
Graph




                      Edge
               A



                             3
Binary Relation


        Hates


  A               B



Itchy           Scratchy



                           4
Binary Relation



         Edge

  A               B


Vertex          Vertex




                         4
Graph


    B       E

                F
A


    D       G




                    5
Undirected Graph


                      B       E


           A


                      D       F




Example: Friendship               6
Directed Edge




  A                B


Vertex        Vertex




                       7
Directed Edge



         Edge

  A                B


Vertex          Vertex




                         7
Directed Graph

         A              B



                    A
                              F

             D




Example: Followee                 8
Path


    B      E

               F
A


    D      G




                   9
Path




A   B   D      G   E   F




                       10
Graph -> GraphDB




GraphDB is a database that use the Graph
     as its primary data structure




                                       11
... when to use a graph ?
Web in ’99




             13
Web in 2005




              14
The social web




                 15
Your data is a graph




                       16
a tree is a graph




                    17
parent_id is a graph




                       18
Recommendations
                                lives in



John                  type           shows
                              Mr
            Fun                                 Cinema B
                             Bean                          loca
                                                               tion
   lik




                                                                      Rome
      es




                                     shows      Cinema A   location
                      type
           Thriller          Se7en
                                      s ho
                                           ws

                                                           location Milan
                                                Cinema C



                                                                             19
Recommendations
                                lives in



John                  type           shows
                              Mr
            Fun                                 Cinema B
                             Bean                          loca
                                                               tion
   lik




                                                                      Rome
      es




                      type
                                     shows      Cinema A   location     ✓

                                                x x
           Thriller          Se7en
                                      s ho
                                           ws

                                                           location Milan
                                                Cinema C



                                                                             20
Recommendations
                                lives in



John                  type           shows
                              Mr
            Fun                                 Cinema B
                             Bean
                                                    ✓      loca
                                                               tion
   lik




                                                                      Rome
      es




                      type
                                     shows      Cinema A   location     ✓

                                                x x
           Thriller          Se7en
                                      s ho
                                           ws

                                                           location Milan
                                                Cinema C



                                                                             21
Recommendations
                                lives in



John                  type           shows
                              Mr
            Fun                                 Cinema B

                               ✓
                             Bean
                                                    ✓      loca
                                                               tion
   lik




                                                                      Rome
      es




                      type
                                     shows      Cinema A   location     ✓

                                                x x
           Thriller          Se7en
                                      s ho
                                           ws

                                                           location Milan
                                                Cinema C



                                                                             22
Recommendations
                                lives in



John

           xFun
                      type    Mr

                               ✓
                             Bean
                                     shows
                                                Cinema B

                                                    ✓      loca
                                                               tion
   lik




                                                                      Rome
      es




                      type
                                     shows      Cinema A   location     ✓

                                                x x
           Thriller          Se7en
                                      s ho
                                           ws

                                                           location Milan
                                                Cinema C



                                                                             23
Recommendations
                                lives in



John

           x x x
            Fun
                      type    Mr
                             Bean
                                     shows
                                                Cinema B
                                                           loca
                                                               tion
   lik




                                                                      Rome
      es




                      type
                                     shows
                                                    ✓
                                                Cinema A   location     ✓

                                                x x
           Thriller          Se7en
                                      s ho
                                           ws

                                                           location Milan
                                                Cinema C



                                                                             24
Recommendations
                                lives in



John

           x x x
            Fun
                      type    Mr
                             Bean
                                     shows
                                             Cinema B
                                                        loca
                                                            tion
   lik




                                                                   Rome
      es




                      type
                                     shows
                                                 ✓
                                             Cinema A   location     ✓
                                ✓ shows
                                             x x
           Thriller          Se7en




                                                        location Milan
                                             Cinema C



                                                                          25
Recommendations
                                lives in



John

           x x x
            Fun
                      type    Mr
                             Bean
                                     shows
                                             Cinema B
                                                        loca
                                                            tion
   lik




                                                                   Rome
      es




                      type
                                     shows
                                                 ✓
                                             Cinema A   location     ✓
                                ✓ shows
                                             x x
               ✓
           Thriller          Se7en




                                                        location Milan
                                             Cinema C



                                                                          26
Recommendations
                                lives in



John

           x x x
            Fun
                      type    Mr
                             Bean
                                     shows
                                             Cinema B
                                                        loca
                                                            tion
   lik




            ✓
                                                                   Rome
      es




                      type
                                     shows
                                                 ✓
                                             Cinema A   location     ✓
                                ✓ shows
                                             x x
               ✓
           Thriller          Se7en




                                                        location Milan
                                             Cinema C



                                                                          27
Solve decision problems
Maximum flow
Graph databases in PHP @ PHPCon Poland 10-22-2011
Given a dataset, calculate how to best organize it
                  maximum flow
travelling salesman problem
The pizza guy needs to deliver on A, B,C.
Decision base on distance, traffic, time and so on.
Shortest path
Identify "special" nodes of the graph
Given your dataset, organize some clusters

   Are there some nodes which cannot belong to a cluster?

They probably have some properties different from the average
Given your dataset, organize some clusters

   Are there some nodes which cannot belong to a cluster?

They probably have some properties different from the average


      ACHTUNG!
    TERRORISTEN!
but ... why graphDB?




                       38
Representing a Graph in:
    http://www.slideshare.net/slidarko/problemsolving-using-graph-traversals-searching-
    scoring-ranking-and-recommendation#




                                                                                   39
Representing a Graph in:
                          http://www.slideshare.net/slidarko/problemsolving-using-graph-traversals-searching-
                          scoring-ranking-and-recommendation#
✓ Relational Database
  (mysql, oracle)




✓ Document Oriented DB
  (mongodb, couchdb)




✓ XML Database
  (MarkLogic, eXist-db)
                                                                                                         39
where is the difference ?




                            40
GraphDB



               A graph database is any storage
               system that provides index-free
               adjacency.




http://www.slideshare.net/slidarko/problemsolving-using-graph-traversals-searching-scoring-ranking-and-recommendation
Step by step example




Given a list of people, find their homepages




                                               42
Tree-based DB WAY




   1




                    43
Tree-based DB WAY



           David Funaro

       put in the Search Engine
                             2




   1




                                  43
Tree-based DB WAY



           David Funaro

       put in the Search Engine
                             2




                                               find   3


   1

                                  http://davidfunaro.com
                                                          43
Tree-based DB WAY



               David Funaro

 The cost to find Search Engine friend HP
            put in the a single
                              2

grows as the friends HP tables grows

                                               find   3


           1

                                  http://davidfunaro.com
                                                          43
GraphDB WAY




it’s like that the GraphDB has an additional information
                      (the ancor <a>)
                                                     44
GraphDB WAY




    1   get the embedded
        information(index)
                                    www.odino.org




it’s like that the GraphDB has an additional information
                      (the ancor <a>)
                                                     44
GraphDB WAY

  The Anchor work as a local index to
   reach the document = index-free
              adjacency

    <a href=”http://odino.org”>
      Alessandro Nadalin
    </a>




                                        45
Local cost



The local cost is O(k) = Constant




                                    46
Local cost




The local cost is O(k) = Constant




                                      47
Local cost




             48
Local cost




   Thus, as the graph grows in size,
the cost of a local step remain the same



                                           48
any database can implicity represent a
               graph

             BUT
only a graph database make the graph
         structure explicit




                                         49
Benchmark


Deph   RDBMS     Graph
 1      100ms     30ms
                                       •       1 Million Vertex

                                       •       4 Million Edge
 2     1000ms    500ms
                                       •       Scale Free Tolopogy
 3     10000ms   3000ms
                                       •       Postgres VS Neo4J
 4     100000m 50000ms
          s                            •       Both Hash and BTree
 5       N/A   100000m
                  s

                                                                                                     50
                 http://markorodriguez.com/2011/02/18/mysql-vs-neo4j-on-a-large-scale-graph-traversal/
community that is building and feeding the GraphDB ecosystem
               GraphDB community



  ThinkerPop
     Stack




                           Databases
data model and their
               implementation




  Blueprints is a collection of interfaces, implementations,
ouplementations, and test suites for the property graph data
 model. Blueprints is analogous to the JDBC, but for graph
                           databases.


                                          https://github.com/tinkerpop/blueprints/wiki/
a data flow Framework using Process Graph




  provide a collection of "pipes" that are
  connected togheter to from processing
                 pipelines
a graph-based programming language.




a Turing-Complete graph-base programming language
     that compiles Gremlin syntax down to Pipes
a REST-full graph shell.




Allow blueprints graph to be exposed
   through a RESTful API (HTTP)
What's hot
OrientDB
Glossary


   RID
  <10:05>
Cluster Position




                   58
Glossary


   RID
  <10:05>
Cluster Position

   CLASS

                   58
Main features
Inheritance
class Vehicle




                     class Car
class Bike
class Vehicle




                          class Car
     class Bike

SELECT FROM Vehicle WHERE owner = 1:1
class Vehicle




                           class Car
      class Bike

can return records of class Bike or Car
Traversal
Graph databases in PHP @ PHPCon Poland 10-22-2011
SELECT FROM fellas WHERE any() traverse(0,-1) ( @rid = [Michelle @rid] )
                                                                     66
SELECT FROM fellas WHERE any() traverse(0,-1) ( @rid = [Michelle @rid] )
                                                                     67
SELECT FROM fellas WHERE any() traverse(0,2) ( @rid = = [Michelle @rid] ))
  SELECT FROM fellas WHERE any() traverse(0,2) ( @rid [Michelle @rid]
SELECT FROM fellas WHERE any() traverse(0,2) ( @rid = [Michelle @rid] )
SQL synthax
beyond SQL
SELECT FROM authors WHERE book.title = ...
ACID
speaks JSON
{ "schema": {
 "name": "Address"
   },
    "result": [{
      "@type": "d", "@rid": "#13:0", "@version": 6, "@class": "Address",
      "type": "Residence",
      "street": "Piazza Navona, 1",
      "city": "#14:0",
      "nick": "Luca2"
    }, {
    ...
    ...
Double Protocol
HTTP
HTTP



Universal
HTTP



Easy to interact with
binary
binary

  Blazing fast
on-record SELECTs
SELECT FROM cats
SELECT FROM cats
SELECT FROM 11:0
SELECT FROM 11:0
SELECT FROM [11:0,11:1]
SELECT FROM [11:0,11:1]
SELECT FROM [11:0,12:0]
SELECT FROM [11:0,12:0]
stress-free setup
2 Mb
./orient/bin/server.sh




                         93
in-memory DB
or disk-persisted
Supports standards   Supports standards




                                          96
•Inheritance
           •Traversal
           •Sql syntax like
           •ACID
OrientDB   •Speak JSON
           •Double protocol
           •on-record Select
           •ThinkerPop Compliant
Oh, it's Java.




                 98
PHP ?
somebody started writing the
   binary-protocol binding
https://github.com/AntonTerekhov/OrientDB-PHP
             ( beta0.4.1, 28 April 2010 )
$db = new OrientDB($host, $port);

$record = $db->recordLoad('1:1', '*:-1');

// $record instance of OrientDBRecord
and others
Graph databases in PHP @ PHPCon Poland 10-22-2011
Orient Library




... are writing a complete library
 https://github.com/congow/Orient




                                     104
Orient = PHP Library to work with OrientDB




                                         105
Data Mapper




Query Builder
                      HTTP Binding
HTTP Binding
use CongowOrient;
use CongowOrientFoundationBinding;

$driver   = new OrientHttpClientCurl();
$orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo');

$response = $orient->query("SELECT FROM Address");

$output   = json_decode($response->getBody());

foreach ($output->result as $address)
{
  var_dump($address->street);
}
use CongowOrient;
use CongowOrientFoundationBinding;

$driver   = new OrientHttpClientCurl();
$orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo');

$response = $orient->query("SELECT FROM Address");

$output   = json_decode($response->getBody());

foreach ($output->result as $address)
{
  var_dump($address->street);
}
use CongowOrient;
use CongowOrientFoundationBinding;

$driver   = new OrientHttpClientCurl();
$orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo');

$response = $orient->query("SELECT FROM Address");

$output   = json_decode($response->getBody());

foreach ($output->result as $address)
{
  var_dump($address->street);
}
use CongowOrient;
use CongowOrientFoundationBinding;

$driver   = new OrientHttpClientCurl();
$orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo');

$response = $orient->query("SELECT FROM Address");

$output   = json_decode($response->getBody());

foreach ($output->result as $address)
{
  var_dump($address->street);
}
use CongowOrient;
use CongowOrientFoundationBinding;

$driver   = new OrientHttpClientCurl();
$orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo');

$response = $orient->query("SELECT FROM Address");

$output   = json_decode($response->getBody());

foreach ($output->result as $address)
{
  var_dump($address->street);              { "schema": {
                                            "name": "Address"
}                                             },
                                                "result": [{
                                                  "@type": "d", "@rid": "#13:0", "@version": 6, "@class": "Address",
                                                  "type": "Residence",
                                                  "street": "Piazza Navona, 1",
                                                  "city": "#14:0",
                                                  "nick": "Luca2"
                                                }, {
                                               ...
                                               ...
apart from ->query($SQL)
->get|delete|postClass($class)
->post|delete|put|getDocument($rid)
...and much more!

(connect, disconnect, ...)
Query Builder
use CongowOrientQuery;

$query = new Query();
$query->from(array('users'))->where('username = ?', "admin");

echo $query->getRaw(); 
// SELECT FROM users WHERE username = "admin"
use CongowOrientQuery;

$query = new Query();
$query->from(array('users'))->where('username = ?', "admin");

echo $query->getRaw(); 
// SELECT FROM users WHERE username = "admin"
use CongowOrientQuery;

$query = new Query();
$query->from(array('users'))->where('username = ?', "admin");

echo $query->getRaw(); 
// SELECT FROM users WHERE username = "admin"
use CongowOrientQuery;

$query = new Query();
$query->from(array('users'))->where('username = ?', "admin");

echo $query->getRaw(); 
// SELECT FROM users WHERE username = "admin"
     $query->select(array('name', 'username', 'email'), false)
      ->from(array('12:0', '12:1'), false)
      ->where('any() traverse ( any() like "%danger%" )')
      ->orWhere("1 = ?", 1)
      ->andWhere("links = ?", 1)
      ->limit(20)
      ->orderBy('username')
      ->orderBy('name', true, true)
      ->range("12:0", "12:1");

    SELECT name, username, email 
    FROM [12:0, 12:1] 
    WHERE any() traverse ( any() like "%danger%" )
    OR 1 = "1" AND links = "1" 
    ORDER BY name, username 
    LIMIT 20 
    RANGE 12:0 12:1
Data Mapper
A Doctrine2 strange ODM
namespace PolandPHPConEntity;

use CongowOrientODMMapperAnnotations as ODM;

/**
* @ODMDocument(class="Person")
*/
class Speaker
{
    /**
     * @ODMProperty( type="string")
     */
    protected $name;

        public function setName($name)
        {
            $this->name = $name;
        }
namespace PolandPHPConEntity;

use CongowOrientODMMapperAnnotations as ODM;

/**
* @ODMDocument(class="Person")
*/
class Speaker
{
    /**
     * @ODMProperty(type="string")
     */
    protected $name;

        public function setName($name)
        {
            $this->name = $name;
        }
namespace PolandPHPConEntity;

use CongowOrientODMMapperAnnotations as ODM;

/**
* @ODMDocument(class="Person")
*/
class Speaker
{
    /**
     * @ODMProperty(type="string")
     */
    protected $name;

        public function setName($name)
        {
            $this->name = $name;
        }
namespace PolandPHPConEntity;

use CongowOrientODMMapperAnnotations as ODM;

/**
* @ODMDocument(class="Person")
*/
class Speaker
{
    /**
     * @ODMProperty(type="string")
     */
    protected $name;

        public function setName($name)
        {
            $this->name = $name;
        }
Domain Driven Design
{ "schema": {
 "name": "Speaker"
   },
    "result": [{
      "@type": "d", "@rid": "#1:0", "@version": 6, "@class": "Speaker",
      "name": "David Coallier"
    }, {
    ...
    ...
{ "schema": {
 "name": "Speaker"
   },
    "result": [{
      "@type": "d", "@rid": "#1:0", "@version": 6, "@class": "Speaker",
      "name": "David Coallier"
    }, {
    ...
    ...




 $david = $mapper->hydrate(json_decode($speaker));
{ "schema": {
 "name": "Speaker"
   },
    "result": [{
      "@type": "d", "@rid": "#1:0", "@version": 6, "@class": "Speaker",
      "name": "David Coallier"
    }, {
    ...
    ...




  $david instanceOf PolandPHPConEntitySpeaker
Repository Pattern




$repo = $manager->getRepository('Speaker')
$speakers = $repo->findAll();
$speaker = $repo->find($rid);
$criteria = array('Name' => 'Lorna');

 $lornas = $repo->findBy($criteria);
$criteria = array(
   'Name'      => 'Lorna',
   'last_name' => 'Jane'
);

$lornaJ = $repo->findOneBy($criteria);
Know your boundaries




                       138
https://github.com/doctrine/common/tree/master/lib/Doctrine/Common/Persistence




                                                                           139
Theory sucks.




                140
Demo
Demo


       Menu items in RDBMS
id type     page   url
1   external NULL http://www.google.com
2   page    1      NULL




                                          142
Demo
            Menu items in OrientDB
                     Link



   PageLink
rid title
             {page
                              ExternalLink
                        rid title       url

9:1 home      1         8:2    google   google.com
                                                     143
That’s all, folks!




                     144
That’s all, folks!

David Funaro
@ingdavidino
http://davidfunaro.com




                                              144
That’s all, folks!

David Funaro                     Alessandro Nadalin
@ingdavidino                                        @_odino_
http://davidfunaro.com                        http://odino.org




                                                                 144
That’s all, folks!

David Funaro                     Alessandro Nadalin
@ingdavidino                                        @_odino_
http://davidfunaro.com                        http://odino.org




                                                                 144
Credits

http://www.flickr.com/photos/sayamindu/5677281218/sizes/l/in/photostream/
         http://farm1.static.flickr.com/182/471383865_79d04aec36_o.png
          http://farm1.static.flickr.com/134/318947873_12028f1b66_b.jpg
   http://www.flickr.com/photos/atomdocs/3275758118/sizes/o/in/photostream/
    http://www.flickr.com/photos/pattipics/5229478393/sizes/o/in/photostream/
   http://www.flickr.com/photos/kongharald/366597251/sizes/o/in/photostream/
                                 http://www.everaldo.com/
    http://www.flickr.com/photos/tusnelda/6140792529/sizes/l/in/photostream/
      http://www.flickr.com/photos/mondi/5368644355/sizes/l/in/photostream/
   http://www.flickr.com/photos/jayneandd/4191106566/sizes/l/in/photostream/
      http://www.flickr.com/photos/jooon/2093253534/sizes/l/in/photostream/
   http://www.flickr.com/photos/bluedharma/89186151/sizes/o/in/photostream/
     http://www.flickr.com/photos/exfordy/2747089295/sizes/l/in/photostream/
 http://www.flickr.com/photos/nostri-imago/3137422976/sizes/o/in/photostream/
  http://www.flickr.com/photos/fionasjournal/379587818/sizes/z/in/photostream/
                  http://www.flickr.com/photos/nperlapro/1297392267/
     http://www.flickr.com/photos/fastphive/28428808/sizes/m/in/photostream/
   http://www.flickr.com/photos/rnugraha/2003147365/sizes/o/in/photostream/
   http://www.flickr.com/photos/zigazou76/4412946911/sizes/l/in/photostream/
    http://www.flickr.com/photos/greatnet/4667555436/sizes/l/in/photostream/
       http://www.flickr.com/photos/mnsc/2768391365/sizes/l/in/photostream/
http://www.flickr.com/photos/christmaswithak/4675962453/sizes/l/in/photostream/
        http://www.amazon.com/Trainspotting-Irvine-Welsh/dp/0393314804
http://www.flickr.com/photos/franconadalin59/5778176872/sizes/l/in/photostream/
         http://farm6.static.flickr.com/5176/5474445627_875d621689_b.jpg
             http://farm3.static.flickr.com/2243/2189435082_a16d3c89ae_b.jpg
              http://farm3.static.flickr.com/2647/3816311930_ac52cff491_o.jpg
  http://i130.photobucket.com/albums/p266/feike1977/PES6-4-3-3defencesettings.jpg
          http://images.usatoday.com/life/_photos/2006/11/30/numb3rs-topper.jpg
  http://www.flickr.com/photos/jakecaptive/3205277810/sizes/l/in/photostream/

More Related Content

PDF
HTTP colon slash slash: end of the road? @ CakeFest 2013 in San Francisco
PPTX
Vbug nov 2010 Visio Validation
PDF
Visio 2010 tips and techniques handouts
PPTX
Sql saturday and share point saturday cambridge 2015 - david parker - visio
PPT
Flexsim y Visio
PPTX
Getting Started with Graph Databases
PDF
A walk in graph databases v1.0
PDF
Graph Theory #searchlove The theory that underpins how all search engines wor...
HTTP colon slash slash: end of the road? @ CakeFest 2013 in San Francisco
Vbug nov 2010 Visio Validation
Visio 2010 tips and techniques handouts
Sql saturday and share point saturday cambridge 2015 - david parker - visio
Flexsim y Visio
Getting Started with Graph Databases
A walk in graph databases v1.0
Graph Theory #searchlove The theory that underpins how all search engines wor...

Viewers also liked (19)

PDF
Large Scale Graph Processing with Apache Giraph
PPTX
Improving and Scaling SCADA Systems: Is WinCC OA Right for Me?
PDF
Big Graph Data
PPT
102602994 wincc-course-ppt
PPSX
SIEMENS PLC S7-300&WINCC COURSE
PDF
Applying large scale text analytics with graph databases
PDF
Graph Databases: Trends in the Web of Data
PPTX
An Introduction to NOSQL, Graph Databases and Neo4j
PDF
Relational to Big Graph
PDF
CS6702 graph theory and applications notes pdf book
PPTX
Interesting applications of graph theory
PDF
introduction to graph theory
PPTX
Introduction to Graph Databases
PDF
NOSQLEU - Graph Databases and Neo4j
PDF
Graph database super star
PDF
(In) Security graph database in real world
PPT
Relations and Functions (Algebra 2)
PDF
Titan: The Rise of Big Graph Data
PDF
Performance
Large Scale Graph Processing with Apache Giraph
Improving and Scaling SCADA Systems: Is WinCC OA Right for Me?
Big Graph Data
102602994 wincc-course-ppt
SIEMENS PLC S7-300&WINCC COURSE
Applying large scale text analytics with graph databases
Graph Databases: Trends in the Web of Data
An Introduction to NOSQL, Graph Databases and Neo4j
Relational to Big Graph
CS6702 graph theory and applications notes pdf book
Interesting applications of graph theory
introduction to graph theory
Introduction to Graph Databases
NOSQLEU - Graph Databases and Neo4j
Graph database super star
(In) Security graph database in real world
Relations and Functions (Algebra 2)
Titan: The Rise of Big Graph Data
Performance
Ad

More from Alessandro Nadalin (20)

PDF
Spa, isomorphic and back to the server our journey with js @ frontend con po...
PDF
SPA, isomorphic and back to the server: our journey with JavaScript @ JsDay 2...
PDF
Scaling at Namshi @ Seamless Ecommerce Dubai 2017
PDF
Accelerated Mobile Pages @ Dubytes meetup Dec 2016 in Dubai
PDF
A tech team of ~10 @ Rocket Tech Summit 2016 in Berlin
PDF
React native in the wild @ Codemotion 2016 in Rome
PDF
Dockerize it! @ Codemotion 2016 in Rome
PDF
Deploying 3 times a day without a downtime @ Rocket Tech Summit in Berlin
PDF
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
PDF
Don't screw it up: how to build durable web apis @ PHPDay 2014 in Verona (ITA)
PDF
Namshi in 2014: let's rock!
PDF
Angular js is the future. maybe. @ ConFoo 2014 in Montreal (CA)
PDF
OrientDB, the fastest document-based graph database @ Confoo 2014 in Montreal...
PDF
A Rocket Internet experience @ ForumPHP Paris 2013
PDF
Tips and Tricks for your Service Oriented Architecture @ CakeFest 2013 in San...
PDF
The rocket internet experience @ PHP.TO.START 2013 in Turin
PDF
GraphDB in PHP @ Codemotion 03/23/2012
PDF
REST in peace @ IPC 2012 in Mainz
PDF
HTTP colon slash slash: the end of the road?
PDF
The state of your own hypertext preprocessor
Spa, isomorphic and back to the server our journey with js @ frontend con po...
SPA, isomorphic and back to the server: our journey with JavaScript @ JsDay 2...
Scaling at Namshi @ Seamless Ecommerce Dubai 2017
Accelerated Mobile Pages @ Dubytes meetup Dec 2016 in Dubai
A tech team of ~10 @ Rocket Tech Summit 2016 in Berlin
React native in the wild @ Codemotion 2016 in Rome
Dockerize it! @ Codemotion 2016 in Rome
Deploying 3 times a day without a downtime @ Rocket Tech Summit in Berlin
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Don't screw it up: how to build durable web apis @ PHPDay 2014 in Verona (ITA)
Namshi in 2014: let's rock!
Angular js is the future. maybe. @ ConFoo 2014 in Montreal (CA)
OrientDB, the fastest document-based graph database @ Confoo 2014 in Montreal...
A Rocket Internet experience @ ForumPHP Paris 2013
Tips and Tricks for your Service Oriented Architecture @ CakeFest 2013 in San...
The rocket internet experience @ PHP.TO.START 2013 in Turin
GraphDB in PHP @ Codemotion 03/23/2012
REST in peace @ IPC 2012 in Mainz
HTTP colon slash slash: the end of the road?
The state of your own hypertext preprocessor
Ad

Recently uploaded (20)

PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Machine learning based COVID-19 study performance prediction
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPT
Teaching material agriculture food technology
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Modernizing your data center with Dell and AMD
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Approach and Philosophy of On baking technology
CIFDAQ's Market Insight: SEC Turns Pro Crypto
MYSQL Presentation for SQL database connectivity
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Network Security Unit 5.pdf for BCA BBA.
Machine learning based COVID-19 study performance prediction
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Teaching material agriculture food technology
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Chapter 3 Spatial Domain Image Processing.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Per capita expenditure prediction using model stacking based on satellite ima...
Encapsulation_ Review paper, used for researhc scholars
Building Integrated photovoltaic BIPV_UPV.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Unlocking AI with Model Context Protocol (MCP)
Modernizing your data center with Dell and AMD
Reach Out and Touch Someone: Haptics and Empathic Computing
The Rise and Fall of 3GPP – Time for a Sabbatical?
Approach and Philosophy of On baking technology

Graph databases in PHP @ PHPCon Poland 10-22-2011

  • 1. GraphDB in PHP Alessandro Nadalin David Funaro 1
  • 2. Agenda •Theory •When to use a graph? •Why graphDB? •The graphDB community •OrientDB •OrientDB in PHP •Demo 2
  • 5. Essential (Theory) G = (V, Vertex Graph 3
  • 6. Essential (Theory) G = (V, Vertex Graph A 3
  • 7. Essential (Theory) G = (V, E) Vertex Graph Edge A 3
  • 8. Essential (Theory) G = (V, E) Vertex Graph Edge A 3
  • 9. Binary Relation Hates A B Itchy Scratchy 4
  • 10. Binary Relation Edge A B Vertex Vertex 4
  • 11. Graph B E F A D G 5
  • 12. Undirected Graph B E A D F Example: Friendship 6
  • 13. Directed Edge A B Vertex Vertex 7
  • 14. Directed Edge Edge A B Vertex Vertex 7
  • 15. Directed Graph A B A F D Example: Followee 8
  • 16. Path B E F A D G 9
  • 17. Path A B D G E F 10
  • 18. Graph -> GraphDB GraphDB is a database that use the Graph as its primary data structure 11
  • 19. ... when to use a graph ?
  • 23. Your data is a graph 16
  • 24. a tree is a graph 17
  • 25. parent_id is a graph 18
  • 26. Recommendations lives in John type shows Mr Fun Cinema B Bean loca tion lik Rome es shows Cinema A location type Thriller Se7en s ho ws location Milan Cinema C 19
  • 27. Recommendations lives in John type shows Mr Fun Cinema B Bean loca tion lik Rome es type shows Cinema A location ✓ x x Thriller Se7en s ho ws location Milan Cinema C 20
  • 28. Recommendations lives in John type shows Mr Fun Cinema B Bean ✓ loca tion lik Rome es type shows Cinema A location ✓ x x Thriller Se7en s ho ws location Milan Cinema C 21
  • 29. Recommendations lives in John type shows Mr Fun Cinema B ✓ Bean ✓ loca tion lik Rome es type shows Cinema A location ✓ x x Thriller Se7en s ho ws location Milan Cinema C 22
  • 30. Recommendations lives in John xFun type Mr ✓ Bean shows Cinema B ✓ loca tion lik Rome es type shows Cinema A location ✓ x x Thriller Se7en s ho ws location Milan Cinema C 23
  • 31. Recommendations lives in John x x x Fun type Mr Bean shows Cinema B loca tion lik Rome es type shows ✓ Cinema A location ✓ x x Thriller Se7en s ho ws location Milan Cinema C 24
  • 32. Recommendations lives in John x x x Fun type Mr Bean shows Cinema B loca tion lik Rome es type shows ✓ Cinema A location ✓ ✓ shows x x Thriller Se7en location Milan Cinema C 25
  • 33. Recommendations lives in John x x x Fun type Mr Bean shows Cinema B loca tion lik Rome es type shows ✓ Cinema A location ✓ ✓ shows x x ✓ Thriller Se7en location Milan Cinema C 26
  • 34. Recommendations lives in John x x x Fun type Mr Bean shows Cinema B loca tion lik ✓ Rome es type shows ✓ Cinema A location ✓ ✓ shows x x ✓ Thriller Se7en location Milan Cinema C 27
  • 38. Given a dataset, calculate how to best organize it maximum flow
  • 40. The pizza guy needs to deliver on A, B,C.
  • 41. Decision base on distance, traffic, time and so on.
  • 43. Identify "special" nodes of the graph
  • 44. Given your dataset, organize some clusters Are there some nodes which cannot belong to a cluster? They probably have some properties different from the average
  • 45. Given your dataset, organize some clusters Are there some nodes which cannot belong to a cluster? They probably have some properties different from the average ACHTUNG! TERRORISTEN!
  • 46. but ... why graphDB? 38
  • 47. Representing a Graph in: http://www.slideshare.net/slidarko/problemsolving-using-graph-traversals-searching- scoring-ranking-and-recommendation# 39
  • 48. Representing a Graph in: http://www.slideshare.net/slidarko/problemsolving-using-graph-traversals-searching- scoring-ranking-and-recommendation# ✓ Relational Database (mysql, oracle) ✓ Document Oriented DB (mongodb, couchdb) ✓ XML Database (MarkLogic, eXist-db) 39
  • 49. where is the difference ? 40
  • 50. GraphDB A graph database is any storage system that provides index-free adjacency. http://www.slideshare.net/slidarko/problemsolving-using-graph-traversals-searching-scoring-ranking-and-recommendation
  • 51. Step by step example Given a list of people, find their homepages 42
  • 53. Tree-based DB WAY David Funaro put in the Search Engine 2 1 43
  • 54. Tree-based DB WAY David Funaro put in the Search Engine 2 find 3 1 http://davidfunaro.com 43
  • 55. Tree-based DB WAY David Funaro The cost to find Search Engine friend HP put in the a single 2 grows as the friends HP tables grows find 3 1 http://davidfunaro.com 43
  • 56. GraphDB WAY it’s like that the GraphDB has an additional information (the ancor <a>) 44
  • 57. GraphDB WAY 1 get the embedded information(index) www.odino.org it’s like that the GraphDB has an additional information (the ancor <a>) 44
  • 58. GraphDB WAY The Anchor work as a local index to reach the document = index-free adjacency <a href=”http://odino.org”> Alessandro Nadalin </a> 45
  • 59. Local cost The local cost is O(k) = Constant 46
  • 60. Local cost The local cost is O(k) = Constant 47
  • 62. Local cost Thus, as the graph grows in size, the cost of a local step remain the same 48
  • 63. any database can implicity represent a graph BUT only a graph database make the graph structure explicit 49
  • 64. Benchmark Deph RDBMS Graph 1 100ms 30ms • 1 Million Vertex • 4 Million Edge 2 1000ms 500ms • Scale Free Tolopogy 3 10000ms 3000ms • Postgres VS Neo4J 4 100000m 50000ms s • Both Hash and BTree 5 N/A 100000m s 50 http://markorodriguez.com/2011/02/18/mysql-vs-neo4j-on-a-large-scale-graph-traversal/
  • 65. community that is building and feeding the GraphDB ecosystem GraphDB community ThinkerPop Stack Databases
  • 66. data model and their implementation Blueprints is a collection of interfaces, implementations, ouplementations, and test suites for the property graph data model. Blueprints is analogous to the JDBC, but for graph databases. https://github.com/tinkerpop/blueprints/wiki/
  • 67. a data flow Framework using Process Graph provide a collection of "pipes" that are connected togheter to from processing pipelines
  • 68. a graph-based programming language. a Turing-Complete graph-base programming language that compiles Gremlin syntax down to Pipes
  • 69. a REST-full graph shell. Allow blueprints graph to be exposed through a RESTful API (HTTP)
  • 72. Glossary RID <10:05> Cluster Position 58
  • 73. Glossary RID <10:05> Cluster Position CLASS 58
  • 76. class Vehicle class Car class Bike
  • 77. class Vehicle class Car class Bike SELECT FROM Vehicle WHERE owner = 1:1
  • 78. class Vehicle class Car class Bike can return records of class Bike or Car
  • 81. SELECT FROM fellas WHERE any() traverse(0,-1) ( @rid = [Michelle @rid] ) 66
  • 82. SELECT FROM fellas WHERE any() traverse(0,-1) ( @rid = [Michelle @rid] ) 67
  • 83. SELECT FROM fellas WHERE any() traverse(0,2) ( @rid = = [Michelle @rid] )) SELECT FROM fellas WHERE any() traverse(0,2) ( @rid [Michelle @rid]
  • 84. SELECT FROM fellas WHERE any() traverse(0,2) ( @rid = [Michelle @rid] )
  • 88. ACID
  • 90. { "schema": { "name": "Address" }, "result": [{ "@type": "d", "@rid": "#13:0", "@version": 6, "@class": "Address", "type": "Residence", "street": "Piazza Navona, 1", "city": "#14:0", "nick": "Luca2" }, { ... ...
  • 92. HTTP
  • 107. 2 Mb
  • 111. Supports standards Supports standards 96
  • 112. •Inheritance •Traversal •Sql syntax like •ACID OrientDB •Speak JSON •Double protocol •on-record Select •ThinkerPop Compliant
  • 114. PHP ?
  • 115. somebody started writing the binary-protocol binding https://github.com/AntonTerekhov/OrientDB-PHP ( beta0.4.1, 28 April 2010 )
  • 116. $db = new OrientDB($host, $port); $record = $db->recordLoad('1:1', '*:-1'); // $record instance of OrientDBRecord
  • 119. Orient Library ... are writing a complete library https://github.com/congow/Orient 104
  • 120. Orient = PHP Library to work with OrientDB 105
  • 121. Data Mapper Query Builder HTTP Binding
  • 123. use CongowOrient; use CongowOrientFoundationBinding; $driver   = new OrientHttpClientCurl(); $orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo'); $response = $orient->query("SELECT FROM Address"); $output   = json_decode($response->getBody()); foreach ($output->result as $address) {   var_dump($address->street); }
  • 124. use CongowOrient; use CongowOrientFoundationBinding; $driver   = new OrientHttpClientCurl(); $orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo'); $response = $orient->query("SELECT FROM Address"); $output   = json_decode($response->getBody()); foreach ($output->result as $address) {   var_dump($address->street); }
  • 125. use CongowOrient; use CongowOrientFoundationBinding; $driver   = new OrientHttpClientCurl(); $orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo'); $response = $orient->query("SELECT FROM Address"); $output   = json_decode($response->getBody()); foreach ($output->result as $address) {   var_dump($address->street); }
  • 126. use CongowOrient; use CongowOrientFoundationBinding; $driver   = new OrientHttpClientCurl(); $orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo'); $response = $orient->query("SELECT FROM Address"); $output   = json_decode($response->getBody()); foreach ($output->result as $address) {   var_dump($address->street); }
  • 127. use CongowOrient; use CongowOrientFoundationBinding; $driver   = new OrientHttpClientCurl(); $orient   = new Binding($driver, '127.0.0.1', '2480', 'admin', 'admin', 'demo'); $response = $orient->query("SELECT FROM Address"); $output   = json_decode($response->getBody()); foreach ($output->result as $address) {   var_dump($address->street); { "schema": { "name": "Address" } }, "result": [{ "@type": "d", "@rid": "#13:0", "@version": 6, "@class": "Address", "type": "Residence", "street": "Piazza Navona, 1", "city": "#14:0", "nick": "Luca2" }, { ... ...
  • 131. ...and much more! (connect, disconnect, ...)
  • 133. use CongowOrientQuery; $query = new Query(); $query->from(array('users'))->where('username = ?', "admin"); echo $query->getRaw();  // SELECT FROM users WHERE username = "admin"
  • 134. use CongowOrientQuery; $query = new Query(); $query->from(array('users'))->where('username = ?', "admin"); echo $query->getRaw();  // SELECT FROM users WHERE username = "admin"
  • 135. use CongowOrientQuery; $query = new Query(); $query->from(array('users'))->where('username = ?', "admin"); echo $query->getRaw();  // SELECT FROM users WHERE username = "admin"
  • 136. use CongowOrientQuery; $query = new Query(); $query->from(array('users'))->where('username = ?', "admin"); echo $query->getRaw();  // SELECT FROM users WHERE username = "admin"
  • 137.    $query->select(array('name', 'username', 'email'), false)     ->from(array('12:0', '12:1'), false)     ->where('any() traverse ( any() like "%danger%" )')     ->orWhere("1 = ?", 1)     ->andWhere("links = ?", 1)     ->limit(20)     ->orderBy('username')     ->orderBy('name', true, true)     ->range("12:0", "12:1");   SELECT name, username, email    FROM [12:0, 12:1]    WHERE any() traverse ( any() like "%danger%" )   OR 1 = "1" AND links = "1"    ORDER BY name, username    LIMIT 20    RANGE 12:0 12:1
  • 140. namespace PolandPHPConEntity; use CongowOrientODMMapperAnnotations as ODM; /** * @ODMDocument(class="Person") */ class Speaker {     /**      * @ODMProperty( type="string")      */     protected $name;     public function setName($name)     {         $this->name = $name;     }
  • 141. namespace PolandPHPConEntity; use CongowOrientODMMapperAnnotations as ODM; /** * @ODMDocument(class="Person") */ class Speaker {     /**      * @ODMProperty(type="string")      */     protected $name;     public function setName($name)     {         $this->name = $name;     }
  • 142. namespace PolandPHPConEntity; use CongowOrientODMMapperAnnotations as ODM; /** * @ODMDocument(class="Person") */ class Speaker {     /**      * @ODMProperty(type="string")      */     protected $name;     public function setName($name)     {         $this->name = $name;     }
  • 143. namespace PolandPHPConEntity; use CongowOrientODMMapperAnnotations as ODM; /** * @ODMDocument(class="Person") */ class Speaker {     /**      * @ODMProperty(type="string")      */     protected $name;     public function setName($name)     {         $this->name = $name;     }
  • 145. { "schema": { "name": "Speaker" }, "result": [{ "@type": "d", "@rid": "#1:0", "@version": 6, "@class": "Speaker", "name": "David Coallier" }, { ... ...
  • 146. { "schema": { "name": "Speaker" }, "result": [{ "@type": "d", "@rid": "#1:0", "@version": 6, "@class": "Speaker", "name": "David Coallier" }, { ... ... $david = $mapper->hydrate(json_decode($speaker));
  • 147. { "schema": { "name": "Speaker" }, "result": [{ "@type": "d", "@rid": "#1:0", "@version": 6, "@class": "Speaker", "name": "David Coallier" }, { ... ... $david instanceOf PolandPHPConEntitySpeaker
  • 148. Repository Pattern $repo = $manager->getRepository('Speaker')
  • 151. $criteria = array('Name' => 'Lorna'); $lornas = $repo->findBy($criteria);
  • 152. $criteria = array( 'Name' => 'Lorna', 'last_name' => 'Jane' ); $lornaJ = $repo->findOneBy($criteria);
  • 156. Demo
  • 157. Demo Menu items in RDBMS id type page url 1 external NULL http://www.google.com 2 page 1 NULL 142
  • 158. Demo Menu items in OrientDB Link PageLink rid title {page ExternalLink rid title url 9:1 home 1 8:2 google google.com 143
  • 160. That’s all, folks! David Funaro @ingdavidino http://davidfunaro.com 144
  • 161. That’s all, folks! David Funaro Alessandro Nadalin @ingdavidino @_odino_ http://davidfunaro.com http://odino.org 144
  • 162. That’s all, folks! David Funaro Alessandro Nadalin @ingdavidino @_odino_ http://davidfunaro.com http://odino.org 144
  • 163. Credits http://www.flickr.com/photos/sayamindu/5677281218/sizes/l/in/photostream/ http://farm1.static.flickr.com/182/471383865_79d04aec36_o.png http://farm1.static.flickr.com/134/318947873_12028f1b66_b.jpg http://www.flickr.com/photos/atomdocs/3275758118/sizes/o/in/photostream/ http://www.flickr.com/photos/pattipics/5229478393/sizes/o/in/photostream/ http://www.flickr.com/photos/kongharald/366597251/sizes/o/in/photostream/ http://www.everaldo.com/ http://www.flickr.com/photos/tusnelda/6140792529/sizes/l/in/photostream/ http://www.flickr.com/photos/mondi/5368644355/sizes/l/in/photostream/ http://www.flickr.com/photos/jayneandd/4191106566/sizes/l/in/photostream/ http://www.flickr.com/photos/jooon/2093253534/sizes/l/in/photostream/ http://www.flickr.com/photos/bluedharma/89186151/sizes/o/in/photostream/ http://www.flickr.com/photos/exfordy/2747089295/sizes/l/in/photostream/ http://www.flickr.com/photos/nostri-imago/3137422976/sizes/o/in/photostream/ http://www.flickr.com/photos/fionasjournal/379587818/sizes/z/in/photostream/ http://www.flickr.com/photos/nperlapro/1297392267/ http://www.flickr.com/photos/fastphive/28428808/sizes/m/in/photostream/ http://www.flickr.com/photos/rnugraha/2003147365/sizes/o/in/photostream/ http://www.flickr.com/photos/zigazou76/4412946911/sizes/l/in/photostream/ http://www.flickr.com/photos/greatnet/4667555436/sizes/l/in/photostream/ http://www.flickr.com/photos/mnsc/2768391365/sizes/l/in/photostream/ http://www.flickr.com/photos/christmaswithak/4675962453/sizes/l/in/photostream/ http://www.amazon.com/Trainspotting-Irvine-Welsh/dp/0393314804 http://www.flickr.com/photos/franconadalin59/5778176872/sizes/l/in/photostream/ http://farm6.static.flickr.com/5176/5474445627_875d621689_b.jpg http://farm3.static.flickr.com/2243/2189435082_a16d3c89ae_b.jpg http://farm3.static.flickr.com/2647/3816311930_ac52cff491_o.jpg http://i130.photobucket.com/albums/p266/feike1977/PES6-4-3-3defencesettings.jpg http://images.usatoday.com/life/_photos/2006/11/30/numb3rs-topper.jpg http://www.flickr.com/photos/jakecaptive/3205277810/sizes/l/in/photostream/