2013-03-01 4 views
6

ArangoDB cung cấp tài liệu và cạnh như là một cách cấp thấp để tạo biểu đồ.Cách di chuyển biểu đồ bằng ArangoDB và PHP

Giả sử chúng tôi đã thiết lập biểu đồ với một số đỉnh và cạnh. Biểu đồ thể hiện mối quan hệ giữa các đỉnh.

v2 là con của v1
v3 là một đứa trẻ của v2
v4 là một đứa trẻ của v3
v5 là một đứa trẻ của v1
v6 là một đứa trẻ của v5

Chúng tôi muốn trở thành khả năng truy vấn:

  1. Con đường từ v4 để V1
  2. Tất cả các hậu duệ của v1
  3. Những đứa trẻ của v1
  4. Tất cả tổ tiên của v4
  5. Các bậc phụ huynh của v4

Làm thế nào để làm điều đó trong PHP?

Trả lời

11

Cách để làm điều này là bằng cách truy vấn ArangoDB bằng AQL (ngôn ngữ truy vấn ArangoDB).

Có một vài lệnh để làm việc với biểu đồ trong AQL. Với PHP, chúng ta phải tạo một câu lệnh với truy vấn và thực hiện điều đó.

Mã được gắn kèm sử dụng hàm TRAVERSAL để cung cấp kết quả cho các truy vấn được đề cập trong câu hỏi.

Kịch bản này thiết lập một tài liệu và một bộ sưu tập cạnh, điền nó với đỉnh và các cạnh kết nối, và cuối cùng là truy vấn để cung cấp kết quả.

Nó có thể được thực hiện như hiện tại và sẽ in ra tất cả các kết quả.

<?php 

namespace triagens\ArangoDb; 


    // use this and change it to the path to autoload.php of the arangodb-php client if you're using the client standalone... 
    // require __DIR__ . '/../vendor/triagens/ArangoDb/autoload.php'; 

// ...or use this and change it to the path to autoload.php in the vendor directory if you're using Composer/Packagist 
require __DIR__ . '/../vendor/autoload.php'; 

// This function will provide us with our pre-configured connection options. 
function getConnectionOptions() 
{ 
    $traceFunc = function ($type, $data) { 
     print "TRACE FOR " . $type . PHP_EOL; 
    }; 

    return array(
     ConnectionOptions::OPTION_ENDPOINT  => 'tcp://localhost:8529/', 
     // endpoint to connect to 
     ConnectionOptions::OPTION_CONNECTION => 'Close', 
     // can use either 'Close' (one-time connections) or 'Keep-Alive' (re-used connections) 
     ConnectionOptions::OPTION_AUTH_TYPE  => 'Basic', 
     // use basic authorization 
     /* 
     ConnectionOptions::OPTION_AUTH_USER  => '',      // user for basic authorization 
     ConnectionOptions::OPTION_AUTH_PASSWD  => '',      // password for basic authorization 
     ConnectionOptions::OPTION_PORT   => 8529,     // port to connect to (deprecated, should use endpoint instead) 
     ConnectionOptions::OPTION_HOST   => "localhost",    // host to connect to (deprecated, should use endpoint instead) 
     */ 
     ConnectionOptions::OPTION_TIMEOUT  => 5, 
     // timeout in seconds 
     //ConnectionOptions::OPTION_TRACE   => $traceFunc,    // tracer function, can be used for debugging 
     ConnectionOptions::OPTION_CREATE  => false, 
     // do not create unknown collections automatically 
     ConnectionOptions::OPTION_UPDATE_POLICY => UpdatePolicy::LAST, 
     // last update wins 
    ); 
} 

// This function tries to create vertices and edges for the example 
function setupVerticesAndEdges($connection, $vertexCollection, $edgeCollection) 
{ 

echo "We are creating 6 vertices...<br> "; 
    //create example documents for the vertices 
    $nameV1  = 'v1'; 
    $documentV1 = Document::createFromArray(
     array('name' => $nameV1, '_key' => $nameV1) 
    ); 
    $nameV2  = 'v2'; 
    $documentV2 = Document::createFromArray(
     array('name' => $nameV2, '_key' => $nameV2) 
    ); 
    $nameV3  = 'v3'; 
    $documentV3 = Document::createFromArray(
     array('name' => $nameV3, '_key' => $nameV3) 
    ); 
    $nameV4  = 'v4'; 
    $documentV4 = Document::createFromArray(
     array('name' => $nameV4, '_key' => $nameV4) 
    ); 
    $nameV5  = 'v5'; 
    $documentV5 = Document::createFromArray(
     array('name' => $nameV5, '_key' => $nameV5) 
    ); 
    $nameV6  = 'v6'; 
    $documentV6 = Document::createFromArray(
     array('name' => $nameV6, '_key' => $nameV6) 
    ); 

    echo "We are creating 5 edges...<br> "; 
    //create example documents for the edges 
    $nameE1  = 'e1'; 
    $documentE1 = Edge::createFromArray(
     array('name' => $nameE1, 'label' => 'child_of') 
    ); 
    $nameE2  = 'e2'; 
    $documentE2 = Edge::createFromArray(
     array('name' => $nameE2, 'label' => 'child_of') 
    ); 
    $nameE3  = 'e3'; 
    $documentE3 = Edge::createFromArray(
     array('name' => $nameE3, 'label' => 'child_of') 
    ); 
    $nameE4  = 'e4'; 
    $documentE4 = Edge::createFromArray(
     array('name' => $nameE4, 'label' => 'child_of') 
    ); 
    $nameE5  = 'e5'; 
    $documentE5 = Edge::createFromArray(
     array('name' => $nameE5, 'label' => 'child_of') 
    ); 


    // Get instances of the vertice- and edgehandlers 
    $documentHandler = new DocumentHandler($connection); 
    $edgeHandler  = new EdgeHandler($connection); 

    // Save the vertices 
    try { 
     // query the given $collectionId by example using the previously declared $exampleDocument array 
     $result['v'][] = $documentHandler->save($vertexCollection, $documentV1); 
     $result['v'][] = $documentHandler->save($vertexCollection, $documentV2); 
     $result['v'][] = $documentHandler->save($vertexCollection, $documentV3); 
     $result['v'][] = $documentHandler->save($vertexCollection, $documentV4); 
     $result['v'][] = $documentHandler->save($vertexCollection, $documentV5); 
     $result['v'][] = $documentHandler->save($vertexCollection, $documentV6); 
    } catch (Exception $e) { 
      // any other error 
      echo ('An error occured. Exception: ' . $e); 
    } 


    // Save the edges 
    try { 
     echo "$nameV2 is a child of $nameV1<br> "; 
     $result['e'][] = $edgeHandler->saveEdge(
      $edgeCollection, 
      $vertexCollection . '/' . $nameV2, 
      $vertexCollection . '/' . $nameV1, 
      $documentE1, 
      $options = array() 
     ); 
     echo "$nameV3 is a child of $nameV2<br> "; 
     $result['e'][] = $edgeHandler->saveEdge(
      $edgeCollection, 
      $vertexCollection . '/' . $nameV3, 
      $vertexCollection . '/' . $nameV2, 
      $documentE2, 
      $options = array() 
     ); 
     echo "$nameV4 is a child of $nameV3<br> "; 
     $result['e'][] = $edgeHandler->saveEdge(
      $edgeCollection, 
      $vertexCollection . '/' . $nameV4, 
      $vertexCollection . '/' . $nameV3, 
      $documentE3, 
      $options = array() 
     ); 
     echo "$nameV5 is a child of $nameV1<br> "; 
     $result['e'][] = $edgeHandler->saveEdge(
      $edgeCollection, 
      $vertexCollection . '/' . $nameV5, 
      $vertexCollection . '/' . $nameV1, 
      $documentE4, 
      $options = array() 
     ); 
     echo "$nameV6 is a child of $nameV5<br> "; 
     $result['e'][] = $edgeHandler->saveEdge(
      $edgeCollection, 
      $vertexCollection . '/' . $nameV6, 
      $vertexCollection . '/' . $nameV5, 
      $documentE5, 
      $options = array() 
     ); 
     echo "<font style='font-family: monospace;'>"; 
     echo "$nameV1<br> "; 
     echo "+ $nameV2<br> "; 
     echo "| + $nameV3<br> "; 
     echo "| | + $nameV4<br> "; 
     echo "+ $nameV5<br> "; 
     echo "+ $nameV5<br> "; 
     echo "| + $nameV6<br> "; 
     echo "</font>"; 

     // return the result; 
     return $result; 
    } catch (Exception $e) { 
      // any other error 
      echo ('An error occured. Exception: ' . $e); 
    } 
} 


// helper function that takes the connection and the query to execute. 
function doAQLQuery($connection, $query) 
{ 
    // query through AQL 

    $statement = new \triagens\ArangoDb\Statement($connection, array(
                    "query"  => '', 
                    "count"  => true, 
                    "batchSize" => 1000, 
                    "_sanitize" => true, 
                   )); 
    $statement->setQuery($query); 
    $cursor = $statement->execute(); 

    $result = $cursor->getAll(); 

    return $result; 
} 


// AQL query example functions 


// Function that gets all paths from vertex v4 to v1 
function getPathFromV4ToV1($connection) 
{ 
    $query = 'FOR p IN PATHS(vertices_20130301_01, edges_20130301_01, "outbound") 
    FILTER p.source._id == "vertices_20130301_01/v4" && p.destination._id == "vertices_20130301_01/v1" 
    RETURN p'; 

    $result = doAQLQuery($connection, $query); 

    return $result; 
} 

// Function that gets the paths to all descendants of v1 

function getPathToAllDescendantsOfV1($connection) 
{ 
    $query = 'FOR p IN TRAVERSAL(vertices_20130301_01, edges_20130301_01, "vertices_20130301_01/v1", "inbound", { 
    strategy: "depthfirst", 
    minDepth:1, 
    paths: true, 
    followEdges: [ { label: "child_of" } ] 

}) 
RETURN p 
'; 

    $result = doAQLQuery($connection, $query); 

    return $result; 
} 

// Function that gets the paths to all children of v1 
function getPathToChildrenOfV1($connection) 
{ 
    $query = 'FOR p IN TRAVERSAL(vertices_20130301_01, edges_20130301_01, "vertices_20130301_01/v1", "inbound", { 
    strategy: "depthfirst", 
    maxDepth: 1, 
    minDepth:1, 
    paths: true, 
    followEdges: [ { label: "child_of" } ] 

}) 
RETURN p 
'; 

    $result = doAQLQuery($connection, $query); 

    return $result; 
} 

// Function that gets the paths to all parents of v4 
function getPathToParentsOfV4($connection) 
{ 
    $query = 'FOR p IN TRAVERSAL(vertices_20130301_01, edges_20130301_01, "vertices_20130301_01/v4", "outbound", { 
    strategy: "depthfirst", 
    maxDepth: 1, 
    minDepth:1, 
    paths: true, 
    followEdges: [ { label: "child_of" } ] 

}) 
RETURN p 
'; 

    $result = doAQLQuery($connection, $query); 

    return $result; 
} 

// Function that gets the paths to all ancestor of v4 
function getPathToAllAncestorsOfV4($connection) 
{ 
    $query = 'FOR p IN TRAVERSAL(vertices_20130301_01, edges_20130301_01, "vertices_20130301_01/v4", "outbound", { 
    strategy: "depthfirst", 
    minDepth:1, 
    paths: true, 
    followEdges: [ { label: "child_of" } ] 

}) 
RETURN p 
'; 

    $result = doAQLQuery($connection, $query); 

    return $result; 
} 

// Function that drops collections given 
function dropCollections($connection, $collections) 
{ 
    // register a collection handler to work with the 'users' collection 
    $collectionHandler = new CollectionHandler($connection); 
    echo "dropping collections..."; 
    try { 
     foreach ($collections as $collection) { 
      $collectionHandler->drop($collection); 
     } 
     echo "dropped.<br>"; 
    } catch (Exception $e) { 
     die ('Could not drop collection. Exception: ' . $e . '<br>'); 
    } 
} 

// ********************************************************************************************************************* 
// Start example code 


// register the connection to ArangoDB 
$connection = new Connection(getConnectionOptions()); 


// register a collection handler to work with the 'users' collection 
$collectionHandler = new CollectionHandler($connection); 


// assign the collection names... 
$vertexCollection = 'vertices_20130301_01'; 
$edgeCollection = 'edges_20130301_01'; 

// finally drop the collections... 
// remark this line if you want to drop the collections by hand. 
dropCollections($connection, array($vertexCollection, $edgeCollection)); 


// create the vertices and edges collections... 
// remark those lines if you want to create the collection by hand. 
echo "creating the '$vertexCollection' vertex collection..."; 
try { 
    $collection = new Collection(); 
    $collection->setName($vertexCollection); 
    $collectionHandler->create($collection); 
    echo "created.<br>"; 
} catch (Exception $e) { 
    echo ('Could not create collection. Exception: ' . $e . '<br>'); 
} 


echo "creating the '$edgeCollection' edge collection..."; 
try { 
    $collection = new Collection(); 
    $collection->setName($edgeCollection); 
    $collection->setType(3); 
    $collectionHandler->create($collection); 
    echo "created.<br>"; 
} catch (Exception $e) { 
    echo ('Could not create collection. Exception: ' . $e . '<br>'); 
} 


// setup our vertices and edges.... 
echo "trying to setup our vertices and edges... <br>"; 
$result = setupVerticesAndEdges($connection, $vertexCollection, $edgeCollection); 


// AQL Examples 

// get the path from vertex v4 to v1 
$result = getPathFromV4ToV1($connection); 
echo "<br>*****************************************<br>"; 
echo "get all paths from vertex v4 to v1<br>"; 
echo "<br>*****************************************<br>"; 
var_dump($result); 


// get the paths to all descendants of v1 
$result = getPathToAllDescendantsOfV1($connection); 
echo "<br>*****************************************<br>"; 
echo "get the paths to all descendants of v1<br>"; 
echo "<br>*****************************************<br>"; 
var_dump($result); 

//get the paths to all children of v1 
$result = getPathToChildrenOfV1($connection); 
echo "<br>*****************************************<br>"; 
echo "get the paths to all children of v1<br>"; 
echo "<br>*****************************************<br>"; 
var_dump($result); 


// get the paths to all ancestors of v4 
$result = getPathToAllAncestorsOfV4($connection); 
echo "<br>*****************************************<br>"; 
echo "get the paths to all ancestors of v4<br>"; 
echo "<br>*****************************************<br>"; 
var_dump($result); 

//get all paths to all parents of v4 
$result = getPathToParentsOfV4($connection); 
echo "<br>*****************************************<br>"; 
echo "get all paths to all parents of v4<br>"; 
echo "<br>*****************************************<br>"; 
var_dump($result);