ArangoDB提供文档和边线作为生成图形的低级方法。

假设我们已经建立了一个带有一些顶点和边的图形。
该图表示顶点之间的关系。

v2是v1的子级
v3是v2的子级
v4是v3的子级
v5是v1的子级
v6是v5的子级

我们希望能够查询:

  • 从v4到v1的路径
  • v1的所有后代
  • v1的子代
  • v4的所有祖先
  • v4的 parent

  • 如何在PHP中做到这一点?

    最佳答案

    做到这一点的方法是使用AQL(ArangoDB查询语言)查询ArangoDB。

    在AQL中有一些用于处理图形的命令。
    使用PHP,我们必须使用查询创建一条语句并执行该语句。

    所附代码使用TRAVERSAL函数,以便将结果提供给问题中提到的查询。

    该脚本设置了一个文档和一个边集合,用顶点和连接边填充它,最后进行查询以提供结果。

    它可以按原样执行,并且将打印出所有结果。

    <?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);
    

    关于arangodb - 如何使用ArangoDB和PHP遍历图形,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15157455/

    10-11 20:43