Giter Site home page Giter Site logo

arangodb-php's Introduction

ArangoDB-PHP - A PHP client for ArangoDB

This driver for ArangoDB, called the ArangoDB-PHP client, allows REST-based access to documents on the server. The DocumentHandler class should be used for these purposes. There is an example for REST-based documents access in the examples/document.php file.

Furthermore, the PHP client also allows to issue more AQL complex queries using the Statement class. There is an example for this kind of statements in the examples/aql-query.php file.

To use the PHP client, you must include the file autoloader.php from the main directory. The autoloader cares about loading additionally required classes on the fly. The autoloader can be nested with other autoloaders.

The ArangoDB PHP client is an API that allows you to send and retrieve documents from ArangoDB from out of your PHP application. The client library itself is written in PHP and has no further dependencies but just plain PHP 5.6 (or higher).

The client library provides document and collection classes you can use to work with documents and collections in an object-oriented fashion. When exchanging document data with the server, the library internally uses the HTTP REST interface of ArangoDB. The library user does not have to care about this fact as all the details of the REST interface are abstracted by the client library.

Requirements

  • PHP version 5.6 or higher

Note on PHP version support:

This driver ceases to support old PHP versions as soon as they have reached end-of-life status. Support is removed with the next minor or patch version of the driver to be released.

In general, it is recommended to always use the latest PHP versions in order to take advantage of all the improvements (especially in performance).

Important version information on ArangoDB-PHP

The ArangoDB-PHP driver version has to match with the ArangoDB version:

  • ArangoDB-PHP v3.8.x is on par with the functionality of ArangoDB v3.8.x
  • ArangoDB-PHP v3.9.x is on par with the functionality of ArangoDB v3.9.x

etc.

Installation using Composer or Git

To get started, you need PHP 5.6 or higher plus an ArangoDB server running on any host that you can access.

There are two alternative ways to get the ArangoDB PHP client:

  • Using Composer
  • Cloning the git repository

Alternative 1: Using Composer

If you use Composer, you can run the following command in a command-line to install the PHP client:

composer require triagens/arangodb

Alternative 2: Cloning the Git repository

When preferring this alternative, you need to have a Git client installed. To clone the ArangoDB-PHP client repository from GitHub, execute the following command in your project directory:

git clone "https://github.com/arangodb/arangodb-php.git"

This creates an arangodb-php subdirectory in your current directory. It contains all the files of the client library. It also includes a dedicated autoloader that you can use for autoloading the client libraries class files. To invoke this autoloader, add the following line to your PHP files that need the library:

require 'arangodb-php/autoload.php';

The ArangoDB-PHP client's autoloader only cares about its own class files and does not handle any other files. That means it is fully nestable with other autoloaders.

If you do not wish to include autoload.php to load and setup the autoloader, you can invoke the autoloader directly:

require 'arangodb-php/lib/ArangoDBClient/autoloader.php';
\ArangoDBClient\Autoloader::init();

Set up the connection

In order to use ArangoDB, you need to specify the connection options. You can do so by creating a PHP array $connectionOptions. Put this code into a file named test.php in your current directory:

// use the following line when using Composer
// require __DIR__ . '/vendor/composer/autoload.php';

// use the following line when using git
require __DIR__ . '/arangodb-php/autoload.php';

// set up some aliases for less typing later
use ArangoDBClient\Collection as ArangoCollection;
use ArangoDBClient\CollectionHandler as ArangoCollectionHandler;
use ArangoDBClient\Connection as ArangoConnection;
use ArangoDBClient\ConnectionOptions as ArangoConnectionOptions;
use ArangoDBClient\DocumentHandler as ArangoDocumentHandler;
use ArangoDBClient\Document as ArangoDocument;
use ArangoDBClient\Exception as ArangoException;
use ArangoDBClient\ConnectException as ArangoConnectException;
use ArangoDBClient\ClientException as ArangoClientException;
use ArangoDBClient\ServerException as ArangoServerException;
use ArangoDBClient\Statement as ArangoStatement;
use ArangoDBClient\UpdatePolicy as ArangoUpdatePolicy;

// set up some basic connection options
$connectionOptions = [
    // database name
    ArangoConnectionOptions::OPTION_DATABASE => '_system',
    // server endpoint to connect to
    ArangoConnectionOptions::OPTION_ENDPOINT => 'tcp://127.0.0.1:8529',
    // authorization type to use (currently supported: 'Basic')
    ArangoConnectionOptions::OPTION_AUTH_TYPE => 'Basic',
    // user for basic authorization
    ArangoConnectionOptions::OPTION_AUTH_USER => 'root',
    // password for basic authorization
    ArangoConnectionOptions::OPTION_AUTH_PASSWD => '',
    // connection persistence on server. can use either 'Close' (one-time connections) or 'Keep-Alive' (re-used connections)
    ArangoConnectionOptions::OPTION_CONNECTION => 'Keep-Alive',
    // connect timeout in seconds
    ArangoConnectionOptions::OPTION_TIMEOUT => 3,
    // whether or not to reconnect when a keep-alive connection has timed out on server
    ArangoConnectionOptions::OPTION_RECONNECT => true,
    // optionally create new collections when inserting documents
    ArangoConnectionOptions::OPTION_CREATE => true,
    // optionally create new collections when inserting documents
    ArangoConnectionOptions::OPTION_UPDATE_POLICY => ArangoUpdatePolicy::LAST,
];

// turn on exception logging (logs to whatever PHP is configured)
ArangoException::enableLogging();

$connection = new ArangoConnection($connectionOptions);

This makes the client connect to ArangoDB

  • running on localhost (OPTION_HOST)
  • on the default port 8529 (OPTION_PORT)
  • with a connection timeout of 3 seconds (OPTION_TIMEOUT)

When creating new documents in a collection that does not yet exist, you have the following choices:

  • auto-generate a new collection: if you prefer that, set OPTION_CREATE to true

  • fail with an error: if you prefer this behavior, set OPTION_CREATE to false

When updating a document that was previously/concurrently updated by another user, you can select between the following behaviors:

  • last update wins: if you prefer this, set OPTION_UPDATE_POLICY to last

  • fail with a conflict error: if you prefer that, set OPTION_UPDATE_POLICY to conflict

Setting up Active Failover

By default, the PHP client connects to a single endpoint only, by specifying a string value for the endpoint in the connection options, e.g.

$connectionOptions = [
    ArangoConnectionOptions::OPTION_ENDPOINT => 'tcp://127.0.0.1:8529'
];

To set up multiple servers to connect to, it is also possible to specify an array of servers instead:

$connectionOptions = [
    ArangoConnectionOptions::OPTION_ENDPOINT    => [ 'tcp://localhost:8531', 'tcp://localhost:8532', 'tcp://localhost:8530' ]
];

Using this option requires ArangoDB 3.3 or higher and the database running in Active Failover mode.

The driver tries to connect to the first server endpoint in the endpoints array by default, and only try the following servers if no connection can be established. If no connection can be made to any server, the driver throws an exception.

As it is unknown to the driver which server from the array is the current leader, the driver connects to the specified servers in array order by default. However, to spare a few unnecessary connection attempts to failed servers, it is possible to set up caching (using Memcached) for the server list. The cached value contains the last working server first, so that as few connection attempts as possible need to be made.

In order to use this caching, it is required to install the Memcached module for PHP, and to set up the following relevant options in the connection options:

$connectionOptions = [
    // memcached persistent id (will be passed to Memcached::__construct)
    ArangoConnectionOptions::OPTION_MEMCACHED_PERSISTENT_ID => 'arangodb-php-pool',

    // memcached servers to connect to (will be passed to Memcached::addServers)
    ArangoConnectionOptions::OPTION_MEMCACHED_SERVERS       => [ [ '127.0.0.1', 11211 ] ],

    // memcached options (will be passed to Memcached::setOptions)
    ArangoConnectionOptions::OPTION_MEMCACHED_OPTIONS       => [ ],

    // key to store the current endpoints array under
    ArangoConnectionOptions::OPTION_MEMCACHED_ENDPOINTS_KEY => 'arangodb-php-endpoints'

    // time-to-live for the endpoints array stored in memcached
    ArangoConnectionOptions::OPTION_MEMCACHED_TTL           => 600
];

Create collections

This is just to show how a collection is created. For these examples it is not needed to create a collection prior to inserting a document, as we set ArangoConnectionOptions::OPTION_CREATE to true.

So, after we get the settings, we can start with creating a collection. We create a collection named users.

The below code first sets up the collection locally in a variable name $user, and then pushes it to the server and returns the collection ID created by the server:

$collectionHandler = new ArangoCollectionHandler($connection);

// clean up first
if ($collectionHandler->has('users')) {
    $collectionHandler->drop('users');
}
if ($collectionHandler->has('example')) {
    $collectionHandler->drop('example');
}

// create a new collection
$userCollection = new ArangoCollection();
$userCollection->setName('users');
$id = $collectionHandler->create($userCollection);

// print the collection id created by the server
var_dump($id);
// check if the collection exists
$result = $collectionHandler->has('users');
var_dump($result);

Create documents

After we created the collection, we can start with creating an initial document. We create a user document in a collection named users. This collection does not need to exist yet. The first document we insert in this collection creates the collection on the fly. This is because we have set OPTION_CREATE to true in $connectionOptions.

The below code first sets up the document locally in a variable name $user, and then pushes it to the server and returns the document ID created by the server:

$handler = new ArangoDocumentHandler($connection);

// create a new document
$user = new ArangoDocument();

// use set method to set document properties
$user->set('name', 'John');
$user->set('age', 25);
$user->set('thisIsNull', null);
$user->set('obj', ['nested' => True]);

// use magic methods to set document properties
$user->likes = ['fishing', 'hiking', 'swimming'];

// send the document to the server
$id = $handler->save('users', $user);

// check if a document exists
$result = $handler->has('users', $id);
var_dump($result);

// print the document id created by the server
var_dump($id);
var_dump($user->getId());

Document properties can be set by using the set() method, or by directly manipulating the document properties.

As you can see, sending a document to the server is achieved by calling the save() method on the client library's DocumentHandler class. It needs the collection name (users in this case) plus the document object to be saved. save() returns the document ID as created by the server. The ID is a numeric value that might or might not fit in a PHP integer.

Add exception handling

The above code works but it does not check for any errors. To make it work in the face of errors, we wrap it into some basic exception handlers:

try {
    $handler = new ArangoDocumentHandler($connection);

    // create a new document
    $user = new ArangoDocument();

    // use set method to set document properties
    $user->set('name', 'John');
    $user->set('age', 25);

    // use magic methods to set document properties
    $user->likes = ['fishing', 'hiking', 'swimming'];

    // send the document to the server
    $id = $handler->save('users', $user);

    // check if a document exists
    $result = $handler->has('users', $id);
    var_dump($result);

    // print the document id created by the server
    var_dump($id);
    var_dump($user->getId());
} catch (ArangoConnectException $e) {
    print 'Connection error: ' . $e->getMessage() . PHP_EOL;
} catch (ArangoClientException $e) {
    print 'Client error: ' . $e->getMessage() . PHP_EOL;
} catch (ArangoServerException $e) {
    print 'Server error: ' . $e->getServerCode() . ':' . $e->getServerMessage() . ' ' . $e->getMessage() . PHP_EOL;
}

Retrieve documents

To retrieve a document from the server, the get() method of the DocumentHandler class can be used. It needs the collection name plus a document ID. There is also the getById() method which is an alias for get().

// get the document back from the server
$userFromServer = $handler->get('users', $id);
var_dump($userFromServer);

/*
The result of the get() method is a Document object that you can use in an OO fashion:

object(ArangoDBClient\Document)##6 (4) {
    ["_id":"ArangoDBClient\Document":private]=>
    string(15) "2377907/4818344"
    ["_rev":"ArangoDBClient\Document":private]=>
    int(4818344)
    ["_values":"ArangoDBClient\Document":private]=>
    array(3) {
        ["age"]=>
        int(25)
        ["name"]=>
        string(4) "John"
        ["likes"]=>
        array(3) {
            [0]=>
            string(7) "fishing"
            [1]=>
            string(6) "hiking"
            [2]=>
            string(8) "swimming"
        }
    }
    ["_changed":"ArangoDBClient\Document":private]=>
    bool(false)
}
*/

Whenever the document ID is yet unknown, but you want to fetch a document from the server by any of its other properties, you can use the CollectionHandler->byExample() method. It allows you to provide an example of the document that you are looking for. The example should either be a Document object with the relevant properties set, or, a PHP array with the properties that you are looking for:

// get a document list back from the server, using a document example
$cursor = $collectionHandler->byExample('users', ['name' => 'John']);
var_dump($cursor->getAll());

This returns all documents from the specified collection (here: users) with the properties provided in the example (here: that have an attribute name with a value of "John"). The result is a cursor which can be iterated sequentially or completely. We have chosen to get the complete result set above by calling the cursor's getAll() method.

CollectionHandler->byExample() returns multiple documents if the example is ambiguous.

Update documents

To update an existing document, the update() method of the DocumentHandler class can be used. In this example we want to:

  • set state to 'CA'
  • change the likes array
// update a document
$userFromServer->likes = ['fishing', 'swimming'];
$userFromServer->state = 'CA';

$result = $handler->update($userFromServer);
var_dump($result);

$userFromServer = $handler->get('users', $id);
var_dump($userFromServer);

To remove an attribute using the update() method, an option has to be passed telling it to not keep attributes with null values. In this example we want to remove the age:

// update a document removing an attribute,
// The 'keepNull'=>false option will cause ArangoDB to
// remove all attributes in the document,
// that have null as their value - not only the ones defined here

$userFromServer->likes = ['fishing', 'swimming'];
$userFromServer->state = 'CA';
$userFromServer->age   = null;

$result = $handler->update($userFromServer, ['keepNull' => false]);
var_dump($result);

$userFromServer = $handler->get('users', $id);
var_dump($userFromServer);

The document that is updated using the previous example must have been fetched from the server before. If you want to update a document without having fetched it from the server before, use updateById():

// update a document, identified by collection and document id
$user        = new ArangoDocument();
$user->name  = 'John';
$user->likes = ['Running', 'Rowing'];

// Notice that for the example we're getting the existing 
// document id via a method call. Normally we would use the known id
$result = $handler->updateById('users', $userFromServer->getId(), $user);
var_dump($result);

$userFromServer = $handler->get('users', $id);
var_dump($userFromServer);

Replace documents

To completely replace an existing document, the replace() method of the DocumentHandler class can be used. In this example we want to remove the state attribute:

// replace a document (notice that we are using the previously fetched document)
// In this example we are removing the state attribute
unset($userFromServer->state);

$result = $handler->replace($userFromServer);
var_dump($result);

$userFromServer = $handler->get('users', $id);
var_dump($userFromServer);

The document that is replaced using the previous example must have been fetched from the server before. If you want to replace a document without having fetched it from the server before, use replaceById():

// replace a document, identified by collection and document id
$user        = new ArangoDocument();
$user->name  = 'John';
$user->likes = ['Running', 'Rowing'];

// Notice that for the example we're getting the existing 
// document id via a method call. Normally we would use the known id
$result = $handler->replaceById('users', $userFromServer->getId(), $user);
var_dump($result);

$userFromServer = $handler->get('users', $id);
var_dump($userFromServer);

Delete documents

To remove an existing document on the server, the remove() method of the DocumentHandler class can be used. remove() just needs the document to be removed as a parameter:

// remove a document on the server, using a document object
$result = $handler->remove($userFromServer);
var_dump($result);

Note that the document must have been fetched from the server before. If you haven't fetched the document from the server before, use the removeById() method. This requires just the collection name (here: users) and the document ID.

// remove a document on the server, using a collection id and document id
// In this example, we are using the id of the document we deleted in the previous example,
// so it will throw an exception here. (we are catching it though, in order to continue)

try {
    $result = $handler->removeById('users', $userFromServer->getId());
} catch (\ArangoDBClient\ServerException $e) {
    $e->getMessage();
}

Drop collections

To drop an existing collection on the server, use the drop() method of the CollectionHandler class. drop() just needs the name of the collection name to be dropped:

// drop a collection on the server, using its name,
$result = $collectionHandler->drop('users');
var_dump($result);

// drop the other one we created, too
$collectionHandler->drop('example');

Run AQL queries

To run an AQL query, use the Statement class.

The method Statement::execute creates a Cursor object which can be used to iterate over the query's result set.

// create a statement to insert 1000 test users
$statement = new ArangoStatement(
    $connection, [
        'query' => 'FOR i IN 1..1000 INSERT { _key: CONCAT("test", i) } IN users'
    ]
);

// execute the statement
$cursor = $statement->execute();

// now run another query on the data, using bind parameters
$statement = new ArangoStatement(
    $connection, [
        'query' => 'FOR u IN @@collection FILTER u.name == @name RETURN u',
        'bindVars' => [
            '@collection' => 'users',
            'name' => 'John'
        ]
    ]
);

// executing the statement returns a cursor
$cursor = $statement->execute();

// easiest way to get all results returned by the cursor
var_dump($cursor->getAll());

// to get statistics for the query, use Cursor::getExtra();
var_dump($cursor->getExtra());

Note: by default the Statement object will create a Cursor that converts each value into a Document object. This is normally the intended behavior for AQL queries that return entire documents. However, an AQL query can also return projections or any other data that cannot be converted into Document objects.

In order to suppress the conversion into Document objects, the Statement must be given the _flat attribute. This allows processing the results of arbitrary AQL queries:

// run an AQL query that does not return documents but scalars
// we need to set the _flat attribute of the Statement in order for this to work
$statement = new ArangoStatement(
    $connection, [
        'query' => 'FOR i IN 1..1000 RETURN i',
        '_flat' => true
    ]
);

// executing the statement returns a cursor
$cursor = $statement->execute();

// easiest way to get all results returned by the cursor
// note that now the results won't be converted into Document objects
var_dump($cursor->getAll());

Bulk document handling

The ArangoDB-PHP driver provides a mechanism to easily fetch multiple documents from the same collection with a single request. All that needs to be provided is an array of document keys:

$exampleCollection = new ArangoCollection();
$exampleCollection->setName('example');
$id = $collectionHandler->create($exampleCollection);

// create a statement to insert 100 example documents
$statement = new ArangoStatement(
    $connection, [
        'query' => 'FOR i IN 1..100 INSERT { _key: CONCAT("example", i), value: i } IN example'
    ]
);
$statement->execute();

// later on, we can assemble a list of document keys
$keys = [];
for ($i = 1; $i <= 100; ++$i) {
    $keys[] = 'example' . $i;
}
// and fetch all the documents at once
$documents = $collectionHandler->lookupByKeys('example', $keys);
var_dump($documents);

// we can also bulk-remove them:
$result = $collectionHandler->removeByKeys('example', $keys);

var_dump($result);

Custom Document class

If you want to use custom document class you can pass its name to DocumentHandler or CollectionHandler using method setDocumentClass. Remember that Your class must extend \ArangoDBClient\Document.

$ch = new CollectionHandler($connection);
$ch->setDocumentClass('\AppBundle\Entity\Product');
$cursor = $ch->all('product'); 
// All returned documents will be \AppBundle\Entity\Product instances

$dh = new DocumentHandler($connection);
$dh->setDocumentClass('\AppBundle\Entity\Product');
$product = $dh->get('products', 11231234);
// Product will be \AppBundle\Entity\Product instance

See the examples/customDocumentClass.php file for more details.

Log exceptions

The driver provides a simple logging mechanism that is turned off by default. If it is turned on, the driver logs all its exceptions using PHP's standard error_log mechanism. It calls PHP's error_log() function for this. It depends on the PHP configuration if and where exceptions are logged. Please consult your php.ini settings for further details.

To turn on exception logging in the driver, set a flag on the driver's Exception base class, from which all driver exceptions are subclassed:

use ArangoDBClient\Exception as ArangoException;

ArangoException::enableLogging();

To turn logging off, call its disableLogging method:

use ArangoDBClient\Exception as ArangoException;

ArangoException::disableLogging();

Put it all together

Here is the full code that combines all the pieces outlined above:

// use the following line when using Composer
// require __DIR__ . '/vendor/composer/autoload.php';

// use the following line when using git
require __DIR__ . '/autoload.php';

// set up some aliases for less typing later
use ArangoDBClient\Collection as ArangoCollection;
use ArangoDBClient\CollectionHandler as ArangoCollectionHandler;
use ArangoDBClient\Connection as ArangoConnection;
use ArangoDBClient\ConnectionOptions as ArangoConnectionOptions;
use ArangoDBClient\DocumentHandler as ArangoDocumentHandler;
use ArangoDBClient\Document as ArangoDocument;
use ArangoDBClient\Exception as ArangoException;
use ArangoDBClient\ConnectException as ArangoConnectException;
use ArangoDBClient\ClientException as ArangoClientException;
use ArangoDBClient\ServerException as ArangoServerException;
use ArangoDBClient\Statement as ArangoStatement;
use ArangoDBClient\UpdatePolicy as ArangoUpdatePolicy;

// set up some basic connection options
$connectionOptions = [
    // database name
    ArangoConnectionOptions::OPTION_DATABASE => '_system',
    // server endpoint to connect to
    ArangoConnectionOptions::OPTION_ENDPOINT => 'tcp://127.0.0.1:8529',
    // authorization type to use (currently supported: 'Basic')
    ArangoConnectionOptions::OPTION_AUTH_TYPE => 'Basic',
    // user for basic authorization
    ArangoConnectionOptions::OPTION_AUTH_USER => 'root',
    // password for basic authorization
    ArangoConnectionOptions::OPTION_AUTH_PASSWD => '',
    // connection persistence on server. can use either 'Close' (one-time connections) or 'Keep-Alive' (re-used connections)
    ArangoConnectionOptions::OPTION_CONNECTION => 'Keep-Alive',
    // connect timeout in seconds
    ArangoConnectionOptions::OPTION_TIMEOUT => 3,
    // whether or not to reconnect when a keep-alive connection has timed out on server
    ArangoConnectionOptions::OPTION_RECONNECT => true,
    // optionally create new collections when inserting documents
    ArangoConnectionOptions::OPTION_CREATE => true,
    // optionally create new collections when inserting documents
    ArangoConnectionOptions::OPTION_UPDATE_POLICY => ArangoUpdatePolicy::LAST,
];


// turn on exception logging (logs to whatever PHP is configured)
ArangoException::enableLogging();

try {
    $connection = new ArangoConnection($connectionOptions);

    $collectionHandler = new ArangoCollectionHandler($connection);

    // clean up first
    if ($collectionHandler->has('users')) {
        $collectionHandler->drop('users');
    }
    if ($collectionHandler->has('example')) {
        $collectionHandler->drop('example');
    }

    // create a new collection
    $userCollection = new ArangoCollection();
    $userCollection->setName('users');
    $id = $collectionHandler->create($userCollection);

    // print the collection id created by the server
    var_dump($id);

    // check if the collection exists
    $result = $collectionHandler->has('users');
    var_dump($result);

    $handler = new ArangoDocumentHandler($connection);

    // create a new document
    $user = new ArangoDocument();

    // use set method to set document properties
    $user->set('name', 'John');
    $user->set('age', 25);
    $user->set('thisIsNull', null);

    // use magic methods to set document properties
    $user->likes = ['fishing', 'hiking', 'swimming'];

    // send the document to the server
    $id = $handler->save('users', $user);

    // check if a document exists
    $result = $handler->has('users', $id);
    var_dump($result);

    // print the document id created by the server
    var_dump($id);
    var_dump($user->getId());


    // get the document back from the server
    $userFromServer = $handler->get('users', $id);
    var_dump($userFromServer);

    // get a document list back from the server, using a document example
    $cursor = $collectionHandler->byExample('users', ['name' => 'John']);
    var_dump($cursor->getAll());


    // update a document
    $userFromServer->likes = ['fishing', 'swimming'];
    $userFromServer->state = 'CA';

    $result = $handler->update($userFromServer);
    var_dump($result);

    $userFromServer = $handler->get('users', $id);
    var_dump($userFromServer);


    // update a document removing an attribute,
    // The 'keepNull'=>false option will cause ArangoDB to
    // remove all attributes in the document,
    // that have null as their value - not only the ones defined here

    $userFromServer->likes = ['fishing', 'swimming'];
    $userFromServer->state = 'CA';
    $userFromServer->age   = null;

    $result = $handler->update($userFromServer, ['keepNull' => false]);
    var_dump($result);

    $userFromServer = $handler->get('users', $id);
    var_dump($userFromServer);


    // replace a document (notice that we are using the previously fetched document)
    // In this example we are removing the state attribute
    unset($userFromServer->state);

    $result = $handler->replace($userFromServer);
    var_dump($result);

    $userFromServer = $handler->get('users', $id);
    var_dump($userFromServer);


    // replace a document, identified by collection and document id
    $user                  = new ArangoDocument();
    $user->name            = 'John';
    $user->likes           = ['Running', 'Rowing'];
    $userFromServer->state = 'CA';

    // Notice that for the example we're getting the existing
    // document id via a method call. Normally we would use the known id
    $result = $handler->replaceById('users', $userFromServer->getId(), $user);
    var_dump($result);

    $userFromServer = $handler->get('users', $id);
    var_dump($userFromServer);


    // remove a document on the server
    $result = $handler->remove($userFromServer);
    var_dump($result);


    // remove a document on the server, using a collection id and document id
    // In this example, we are using the id of the document we deleted in the previous example,
    // so it will throw an exception here. (we are catching it though, in order to continue)

    try {
        $result = $handler->removeById('users', $userFromServer->getId());
    } catch (\ArangoDBClient\ServerException $e) {
        $e->getMessage();
    }



    // create a statement to insert 1000 test users
    $statement = new ArangoStatement(
        $connection, [
            'query' => 'FOR i IN 1..1000 INSERT { _key: CONCAT("test", i) } IN users'
        ]
    );

    // execute the statement
    $cursor = $statement->execute();


    // now run another query on the data, using bind parameters
    $statement = new ArangoStatement(
        $connection, [
            'query' => 'FOR u IN @@collection FILTER u.name == @name RETURN u',
            'bindVars' => [
                '@collection' => 'users',
                'name' => 'John'
            ]
        ]
    );

    // executing the statement returns a cursor
    $cursor = $statement->execute();

    // easiest way to get all results returned by the cursor
    var_dump($cursor->getAll());

    // to get statistics for the query, use Cursor::getExtra();
    var_dump($cursor->getExtra());


    $exampleCollection = new ArangoCollection();
    $exampleCollection->setName('example');
    $id = $collectionHandler->create($exampleCollection);

    // create a statement to insert 100 example documents
    $statement = new ArangoStatement(
        $connection, [
            'query' => 'FOR i IN 1..100 INSERT { _key: CONCAT("example", i), value: i } IN example'
        ]
    );
    $statement->execute();

    // later on, we can assemble a list of document keys
    $keys = [];
    for ($i = 1; $i <= 100; ++$i) {
        $keys[] = 'example' . $i;
    }
    // and fetch all the documents at once
    $documents = $collectionHandler->lookupByKeys('example', $keys);
    var_dump($documents);

    // we can also bulk-remove them:
    $result = $collectionHandler->removeByKeys('example', $keys);

    var_dump($result);


    // drop a collection on the server, using its name,
    $result = $collectionHandler->drop('users');
    var_dump($result);

    // drop the other one we created, too
    $collectionHandler->drop('example');
} catch (ArangoConnectException $e) {
    print 'Connection error: ' . $e->getMessage() . PHP_EOL;
} catch (ArangoClientException $e) {
    print 'Client error: ' . $e->getMessage() . PHP_EOL;
} catch (ArangoServerException $e) {
    print 'Server error: ' . $e->getServerCode() . ': ' . $e->getServerMessage() . ' - ' . $e->getMessage() . PHP_EOL;
}

More information

  • More example code, containing some code to create, delete and rename collections, is provided in the examples subdirectory that is provided with the library.

  • PHPDoc documentation for the complete library

arangodb-php's People

Contributors

13abylon avatar a-shafaat avatar beldur avatar diabl0 avatar dothebart avatar f21 avatar fceller avatar frankmayer avatar hwde avatar ivanignatiev avatar jsteemann avatar luebbert42 avatar m0ppers avatar maxkernbach avatar olivermack avatar sandrokeil avatar scottashton avatar simran-b avatar sleto-it avatar sonyarianto avatar tomterl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arangodb-php's Issues

Refactor function names to better match the server api

We should refactor the function names in the classes to better reflect the server api functions for more uniformity.
Here's what has to be done.

in issue #13 @jsteemann wrote:

The APIs changed several times in the beginning. The PHP client API for example does not have a db class/object at all, so there is not use case for the underscore methods in it.
My suggestion for collection method names in the PHP API (class CollectionHandler) therefore is:

  • delete(): rename to drop() and make delete() call drop(). delete() should be marked as deprecated
  • add(): rename to create() and make add() call create(). add() should be marked as deprecated.
  • getFigures(): rename to figures() and make getFigures() call figures(). getFigures() should be marked as deprecated.
  • getCount(): rename to count() and make getCount() call count(). getCount() should be marked as deprecated.
  • get(): not sure about this. In the server API this method does not have a name, it's simply db.COLLECTIONNAME there. Probably leave it like it is?

Then there's the DocumentHandler:

  • getByExample(): rename to byExample() and move into CollectionHandler. make DocumentHandler::getByExample() call CollectionHandler::byExample(). getByExample() should be marked as deprecated
  • getAllIds(): move to CollectionHandler and make DocumentHandler::getAllIds() call CollectionHandler::getAllids(). DocumentHandler::getAllIds() should be marked as deprecated
  • get(): no idea for this. Probably leave it like it is?
  • getById(): same
  • add(): rename to save() and make add() call save(). add() should be marked as deprecated
  • update(): rename to replace() and make update() call replace(). update() should be marked as deprecated. Announce new meaning for update() in ArangoDB 1.1 (will support HTTP patch method to partially update documents)
  • updateById(): rename to replaceById() and make updateById() call replaceById(). updateById() should be marked as deprecated. Announce new meaning for updateById() in ArangoDB 1.1 (will support HTTP patch method to partially update documents)
  • delete(): rename to remove() and make delete() call remove(). delete() should be marked as deprecated

Character encoding and json_encode leads to data loss

While testing the php driver for arangodb today, I came accross a problem with json_encode returning null in DocumentHandler->save() that would lead to partial data loss.

It was caused when copying strings out of mysql that were encoded in ISO-8859-1 with german special chars.

PHP issued a :
"PHP Warning: json_encode(): Invalid UTF-8 sequence in argument in /var/www/ArangoDB-PHP/lib/triagens/ArangoDb/DocumentHandler.php on line 164"
without any hint of a dataset that created that conversion failure. Also the save was succesful, just the value of the key that failed was 'null'.

To allow only valid UTF-8 strings for importing to the db makes sense and is not the issue here. But I think the failed json encoding should lead to an exception and block the saving of the document.

Possible solution:

foreach ($data as $key=>$value) {
if (is_null(json_encode($value)) && strlen($value)>0) {
throw new ClientException('Json encode failure while saving '. $key. ' in : '.var_export($data));
}
}
$response = $this->getConnection()->post($url, json_encode($data));

Fix request: Something's wrong with paths in the repo

I cannot clone the repo in a correct manner.
I get failures in docs/namespaces and docs/classes.

See the log below for example, there mixed slashes. in the beginning there are forward slahses and after classes and namespaces respsctively there are backslashes. This confuses even Github. Try to browse those directories. After one gets into classes for example, the remaining path and filename is treated as the filename. Something went really wrong there...

git.exe clone --progress -v "https://github.com/frankmayer/ArangoDB-PHP.git" "C:\ArangoDB-PHP"

Cloning into 'C:\ArangoDB-PHP'...
POST git-upload-pack (574 bytes)
remote: Compressing objects: 100% (670/670)
Receiving objects: 100% (1146/1146), 668.00 KiB | 162 KiB/s
Receiving objects: 100% (1146/1146), 710.22 KiB | 162 KiB/s, Resolving deltas: 100% (810/810)
Resolving deltas: 100% (810/810), done.
remote: Total 1146 (delta 810), reused 779 (delta 443)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Autoloader.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\BindVars.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\ClientException.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Collection.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\CollectionHandler.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\ConnectException.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Connection.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\ConnectionOptions.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Cursor.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\DefaultValues.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Document.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\DocumentHandler.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Endpoint.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Exception.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Handler.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\HttpHelper.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\HttpResponse.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Scope.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\ServerException.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\Statement.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\URLHelper.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\URLs.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\UpdatePolicy.html (No such file or directory)
error: unable to create file docs/classes/db_\triagens\ArangoDb\ValueValidator.html (No such file or directory)
error: unable to create file docs/namespaces/db_triagens\ArangoDb.html (No such file or directory)
Success

[1.2] RFC: Implementation of the Graph API in the PHP Client

I am thinking of the best way to implement the graph api into the PHP Client.

Basically I see two options.

The first,

Implement a graph handler and a graph class which will include all functionality for graphs.
The vertices and edges would be prepared and returned using the new graph class.

The second:

Implement a graph handler and a graph class which will only provide the interface for creating and modifying a graph itself.
But depending on the call, return either documents (the vertices) or edges using the existing documents and collection classes..
This would be kind of like the existing "simple" query api usage inside the documents and collection classes.

I personally favor the second one, as it offers more integration and code-reuse. It also doesn't put boundaries on the usage of the models.

What do you think?

Combine add() and update() to store().

Currently, there are separate methods for add()ing and update()ing documents.

I think the API can be cleaner if we just have a store() method. A readonly property inside the Document class can provide information on whether the document should be added or updated.

What do you think?

Collection.all()

it might be also nice to have an equivalent to collection.all() in the PHP driver ... not life-threatening, but nice...

Allow edge object to be passed into replace, remove and update edge

Not sure how feasible this is yet.

Sometimes, we retrieve an edge and have an edge object. We then wish to replace, remove or update this edge.

It is a bit cumbersome trying to get the $edgeId to pass it to the replace, remove and update edge functions.

Perhaps we can allow passing in the edge object as well and have the function grab the edgeId form the edge object.

Constructor for document not saving $options

@frankmayer: I just ran into a problem where $options passed to the constructor of Document is not saved.

Looking at the constructor:

    public function __construct(array $options = array())
    {
        // keeping the non-underscored version for backwards-compatibility
        $this->setChanged(false);
        if (array_key_exists('hiddenAttributes', $options)) {
            $this->setHiddenAttributes($options['hiddenAttributes']);
        }
        if (array_key_exists('_hiddenAttributes', $options)) {
            $this->setHiddenAttributes($options['_hiddenAttributes']);
        }
    }

It looks like if I call new Document(array('_key' => 'test')); the array passed to the constructor will never be saved. Is this intentional?

typo in example code in readme.md

while playing around with the arangodb php client for my thesis I noticed that there is a typo in the example in the readme.md

The "D" in ...\ArangoDb... has to be uppercase in the following statements:

use triagens\ArangoDb\Connection as ArangoConnection;
use triagens\ArangoDb\ConnectionOptions as ArangoConnectionOptions;
use triagens\ArangoDb\DocumentHandler as ArangoDocumentHandler;
use triagens\ArangoDb\Document as ArangoDocument;
use triagens\ArangoDb\Exception as ArangoException;
use triagens\ArangoDb\ConnectException as ArangoConnectException;
use triagens\ArangoDb\ClientException as ArangoClientException;
use triagens\ArangoDb\ServerException as ArangoServerException;
use triagens\ArangoDb\UpdatePolicy as ArangoUpdatePolicy;

Suggestion: Introduce Collection::getProperties and setProperties

When I was about to start modifying the collection class, I noticed that the journalSize property is also missing.

I am thinking of introducing a collection properties getter/setter where one can pass an array of properties. This reflects the actual ArangoDB property function and is also more future proof.

What do you think?

Incomplete feature set in replaceById(): Implement revision check (pass url rev parameter)

I just found out that the replace method isn't implementing the revision check. I have implemented this in my local repo and it functions as follows.

If the document attributes have a _rev attribute then a rev parameter is appended to the url with the revision as its value. Of course the policy should be set to ERROR in this case, or the REST interface will not honor the revision check. BTW is that correct behavior on the REST interface, that the revision is ignored if policy is set to LAST?

Proposal: CollectionHandler->create() should also support an array or even only a string instead of only a collection object

I'd like to implement it like:

$collectionHandler->create('myNewCollection');

We could even implement a second optional parameter $options like the one that is available on other methods of the client, in order to pass options.
Like:

$collectionHandler->create('myNewCollection', array('waitForSync'=>true));

If arangodb/arangodb#423 would be implemented, we could also do:

$collectionHandler->create(array('name'=>'myNewCollection', 'somekey'=>'someValue'), array('waitForSync'=>true));

What do you think?

Should replace() also update the revision in the document?

When I do the following:

//Get existing document
$document = $handler->get(...);
var_dump($document->getRevision());

$handler->replace($document);
var_dump($document->getRevision());

It looks like currently, when we call replace(), the revision is not updated in the document object.

Should we update the handler to update the revision in the document object?

statement breaks when AQL does not return a document

If we have an AQL query like so:

For u in mycollection return u.name

The Cursor class breaks because each document returned is a string. The same goes for any case where the document returned is not an object.

Catchable fatal error: Argument 1 passed to triagens\ArangoDb\Document::createFromArray() must be of the type array, string given, called in /www/ArangoDB-PHP/lib/triagens/ArangoDb/Cursor.php on line 298 and defined in /www/ArangoDB-PHP/lib/triagens/ArangoDb/Document.php on line 142

Backtrace:

1   0.0747  397072  triagens\ArangoDb\Statement->execute( ) ../Query.php:23
2   0.0769  399708  triagens\ArangoDb\Cursor->__construct( )    ../Statement.php:187
3   0.0769  400976  triagens\ArangoDb\Cursor->add( )    ../Cursor.php:127
4   0.0769  401032  triagens\ArangoDb\Cursor->addDocumentsFromArray( )  ../Cursor.php:271
5   0.0769  401376  triagens\ArangoDb\Document::createFromArray( )  ../Cursor.php:298

Cannot run AQL queries that produce non-document results

When running an AQL query using the PHP driver, the result returned by the server may be based on documents, but may be not.
For example, the following query result is based on documents:
FOR e IN example RETURN e
but the following is not:
RETURN UNIQUE([1, 2, 1])

The problem is that when using the PHP driver to execute an AQL query, it produces documents from it. And document must have string keys, at least the driver checks for it in Document.php:186. The above result "document" will only have a key of int(0), so the valid query result cannot be handled by the driver.

Reproduce code:

$connection = new Connection($connectionOptions);
$stmt = new Statement($connection, array("query" => "RETURN UNIQUE([1])"));
$cursor = $stmt->execute();
var_dump($cursor->getAll());

Produces:

PHP Fatal error:  Uncaught triagens\ArangoDb\ClientException: Invalid document attribute key
  thrown in /home/triagens03/steemann/tivian/ArangoDB-PHP/lib/triagens/ArangoDb/Document.php on line 187

Should produce:
the actual result of the query

unique is not avalible for all indices

unique is not available for all types of indices as outlined in the docs.

Jan has updated the docs as per this issue: arangodb/arangodb#481. It should be on the arangodb site soon.

We need to remove the $unique argument from createIndex() in CollectionHandler.

Change Request: Document->createFromArray($array) should set "Changed" flag to true instead of false

I bumped into this while writing a wrapper function for an ODM-Bundle I am writing for Laravel (PHP.) .

It will soon be on Github, once I declare it stable enough for other users to work with it. (Maybe to day or tomorrow).

The save() function from the ODM is checking if the document has changed before actually saving it.

The problem arises when a document is created from an array. In the method it sets Changed to false.

I believe this is a wrong behavior, since it is changed from nothing to a document with data which hasn't been saved to the collection.

The change is a simple replace of false to true in Document.php Line76.

A possible enhancement to the autoloader

Currently there's autoload.php which requires autoloader.php and registers it using spl_autoloader_register.

How do you guys feel about the following:

  • Remove autoload.php.
  • People who want to use the autoloader directly includes autoloader.php
  • Autoloader::init() inits the autoloader and registers it using spl_autoloader_register().

So now, what you need to do is:

require_once('path/to/autoloader.php');
\triagens\ArangoDb\Autoloader::init();

Suggestion: Write Unit tests

I'd like to propose to start writing unit tests for the API.

So we'll also can do ci testing, if and when we can have Arango tests in travis-ci.

I could start writing some tests in the next few days to get things started.

Is PHPUnit OK, or do you favor some other?

"$label" for edge labels

I noticed that in saveEdge() the label of the edge is saved under a property called $label:

public function saveEdge($graphName, $from, $to, $label = null, $document)
{
        if (!is_null($label)) {
            $document->set('$label', $label);
        }

        .....
}

Is this intentional? It makes querying a bit more awkward: u.x.y.$label.

Graph exists function

I think it would be nice to have a function (quite possibly in GraphHandler) to check the existence of a graph.

Is GraphHandler the best place for this?

Should the exists() just return booleans (true, false), or should we return a graph if it does exist? Maybe we can let the consumer of the API set a flag to see if they want just a boolean or a graph if it does exist.

Force graph name in graph() constructor

Since the name of the graph is always required, what do you guys think if we make that a requirement in the graph constructor:

Instead of:

$graph        = new Graph();
$graph->set('_key', 'Graph');

We just do:

$graph = new Graph('myGraph');

Let me know what you guys think :)

1.2.0 Stable Release Tasklist

arangodb-php 1.2.0 Stable Release Tasklist

Things to get done before stable release 1.2.0

  • Implement Graph API => #31
  • Implement New API commands replaceByExample & updateByExample => #40
  • Implement Admin API
  • prefix internal options on methods with an underscore
  • Implement new User API

Should we deprecate autoload.php and do some code organization?

Should we deprecate autoload.php and make invoking the autoloader directly the preferred approach?

Another approach would be to move autoload.php into the ArangoDB folder.

What do you guys think about moving the different PHP files into folders? For example, all the graph stuff in one folder etc.

This would break backwards compatibility though because the namespace will need to change to comply with psr-0 standards.

Let me know what you guys think :)

GraphHandler's getConnectedEdges() returning documents and not edges.

getConnectedEdges() returns a cursor which return Document objects to represent each edge.

It should return Edge objects to represent each edge. I have not really looked into Cursor, but I think some refactoring needs to be done in there to support Edge and Vertex objects.

doctrine style documents

hi,

i would like to ask if you plan to support document classes just like doctrine does for example in its odm. with annotations and all that. because what i can see is that for every object i want to add to db i need to create an instance of a generic base document class, set all properties and save it. so i'm not working with domain objects, but with low level approach.

if your odm was in the style of doctrine's odm, then it would be super cool!

Splitting of ArangoDB-PHP into core and higher level ODM

This is an issue to introduce and follow-up on the progress of splitting the ArangoDB-PHP client.

Introduction:
I am in the process of splitting the driver into core and higher level ODM`.
The core-client will provide connectivity to the API's provided by ArangoDB and the goal is for it to stay as light as possible without providing additional functionality.

All additional functionality will be provided by the higher level part.

This whole idea of doing this, is to provide a basic and light foundation where higher level implementations can be built upon.

For example: Doctrine ODM or a Laravel specific implementation

For special needs, instead of using the provided higher level drivers, one could also write his/her own driver on top of core

Please comment on this issue if you have any suggestions / ideas on this.

Thank you :)

saveEdge() should allow $document to be null

Many times, I just need to create a simple edge between 2 vertices with a label.

In this case, I do not need to set attributes of any type on an edge and it is cumbersome to manually instantiate that edge.

Currently, the method signature for saving an edge is:

public function saveEdge($graphName, $from, $to, $label = null, $document)

I propose that we set it to this:

public function saveEdge($graphName, $from, $to, $label = null, $document =null)

If $document is null, the method can simply create a new edge automatically. The only problem is that we might want the edge object back, so in this case, it will need to return the edge object.

Comments welcome 😄

Separate travis tests against devel of arangodb?

I am building and testing this driver against the devel of arangodb (because I am planning to use the latest features in one of my apps).

When running phpunit, I am getting a few tests that consistently fails, while the current travis tests against 1.2.0 passes fine.

I propose that we have a totally separate test against the devel or arangodb. This means we will have 2 build status images.

The benefit of this is that sometimes, when things like the statistics are disabled, the statistics tests will fail. And we can just leave it alone in the failing state.

However, I am also seeing GraphExtendedTest::testSaveVerticesAndSaveReplaceUpdateAndRemoveEdge and a few others failing, so we can quickly fix those.

So, in other words, we have a travis for the latest stable version of arangodb, and a travis for the bleeding-edge devel. If the bleeding edge devel fails, it is not a really big issue due to things like statistics being disabled. But if we find something we can fix immediately, then that is good because, now, potential bugs that wait until an arangodb release is cut down the road is now fixed immediately.

Let me know what you guys think :)

Question on ServerException class

This is how it looks in symfony when the driver throws an exception - not really self-explaining without the additional information available via getDetails. I was wondering if there is a reason why the details are not in $e->getMessage().

Why does it bother me? For Symfony I have to implement a custom error handling thing to access getDetails() on application level, this is something I don't want to do just for one library in my stack. Am I getting the concept wrong?

screenshot_01

Enhanced tracer

Tracer current receives 2 pieces of data:

  • Type (send/receive)
  • Data: a string that contains the HTTP headers and data.

I propose that we enhance the tracer so that data is an object that contains:

  • Headers in an array
  • Data as an object (or many json string)
  • Method as a string

The benefit of this is that when users supply a tracer, they can do all sorts of things with the trace data and it provides a model that is more flexible to use.

What do you guys think?

Feature: implement missing simple-query-related functionality

in #15 @jsteemann wrote:
I was thinking about some simple-query-related functionality that I think is missing at the moment, e.g. geo index queries etc.

Here are the proposed commands:

CollectionHandler->range($collectionId, $attribute, $left, $right, $options);

CollectionHandler->near($collectionId, $latitude, $longitude, $options);

CollectionHandler->within($collectionId, $latitude, $longitude, $radius, $options);

Invalid response, while it shouldn't

I am doing an AQL query via the php api but it fails

Client error: Got an invalid response from the server

The same query works fine via the Web Interface (query tab).

This is the query:

FOR a in myCollection
FILTER a.`some key` > 40
LIMIT 50
RETURN a

The collection is big and the query can take about 15-20 seconds to get the results via the web interface

The interesting thing is that this query works fine via the php api:

LET C = (RETURN FULLTEXT(myCollection, "Title", "someWord"))
LET D = C[0]
FOR a in D
FILTER a.`some key` > 40
LIMIT 50
RETURN a

This one executes faster than the previous one.

I should mention that I 'm building the query string with concatenation, not bindVars.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.