ArangoDB-PHP API Documentation
  • Namespace
  • Class
  • Deprecated

Namespaces

  • triagens
    • ArangoDb

Classes

  • triagens\ArangoDb\AdminHandler
  • triagens\ArangoDb\AqlUserFunction
  • triagens\ArangoDb\Autoloader
  • triagens\ArangoDb\Batch
  • triagens\ArangoDb\BatchPart
  • triagens\ArangoDb\BindVars
  • triagens\ArangoDb\Collection
  • triagens\ArangoDb\CollectionHandler
  • triagens\ArangoDb\Connection
  • triagens\ArangoDb\ConnectionOptions
  • triagens\ArangoDb\Cursor
  • triagens\ArangoDb\Database
  • triagens\ArangoDb\DefaultValues
  • triagens\ArangoDb\Document
  • triagens\ArangoDb\DocumentHandler
  • triagens\ArangoDb\Edge
  • triagens\ArangoDb\EdgeDefinition
  • triagens\ArangoDb\EdgeHandler
  • triagens\ArangoDb\Endpoint
  • triagens\ArangoDb\Export
  • triagens\ArangoDb\ExportCursor
  • triagens\ArangoDb\Graph
  • triagens\ArangoDb\GraphHandler
  • triagens\ArangoDb\Handler
  • triagens\ArangoDb\HttpHelper
  • triagens\ArangoDb\HttpResponse
  • triagens\ArangoDb\QueryCacheHandler
  • triagens\ArangoDb\QueryHandler
  • triagens\ArangoDb\Statement
  • triagens\ArangoDb\TraceRequest
  • triagens\ArangoDb\TraceResponse
  • triagens\ArangoDb\Transaction
  • triagens\ArangoDb\Traversal
  • triagens\ArangoDb\UpdatePolicy
  • triagens\ArangoDb\UrlHelper
  • triagens\ArangoDb\Urls
  • triagens\ArangoDb\User
  • triagens\ArangoDb\UserHandler
  • triagens\ArangoDb\ValueValidator
  • triagens\ArangoDb\Vertex
  • triagens\ArangoDb\VertexHandler

Exceptions

  • triagens\ArangoDb\ClientException
  • triagens\ArangoDb\ConnectException
  • triagens\ArangoDb\Exception
  • triagens\ArangoDb\ServerException
   1 <?php
   2 
   3 /**
   4  * ArangoDB PHP client: collection handler
   5  *
   6  * @package   triagens\ArangoDb
   7  * @author    Jan Steemann
   8  * @copyright Copyright 2012, triagens GmbH, Cologne, Germany
   9  */
  10 
  11 namespace triagens\ArangoDb;
  12 
  13 /**
  14  * Provides management of collections
  15  *
  16  * The collection handler fetches collection data from the server and
  17  * creates collections on the server.
  18  *
  19  * @package   triagens\ArangoDb
  20  * @since     0.2
  21  */
  22 class CollectionHandler extends
  23     Handler
  24 {
  25 
  26     /**
  27      * documents array index
  28      */
  29     const ENTRY_DOCUMENTS = 'documents';
  30 
  31     /**
  32      * collection parameter
  33      */
  34     const OPTION_COLLECTION = 'collection';
  35 
  36     /**
  37      * example parameter
  38      */
  39     const OPTION_EXAMPLE = 'example';
  40 
  41     /**
  42      * example parameter
  43      */
  44     const OPTION_NEW_VALUE = 'newValue';
  45 
  46     /**
  47      * example parameter
  48      */
  49     const OPTION_CREATE_COLLECTION = 'createCollection';
  50 
  51     /**
  52      * attribute parameter
  53      */
  54     const OPTION_ATTRIBUTE = 'attribute';
  55 
  56     /**
  57      * keys parameter
  58      */
  59     const OPTION_KEYS = 'keys';
  60 
  61     /**
  62      * left parameter
  63      */
  64     const OPTION_LEFT = 'left';
  65 
  66     /**
  67      * right parameter
  68      */
  69     const OPTION_RIGHT = 'right';
  70 
  71     /**
  72      * closed parameter
  73      */
  74     const OPTION_CLOSED = 'closed';
  75 
  76     /**
  77      * latitude parameter
  78      */
  79     const OPTION_LATITUDE = 'latitude';
  80 
  81     /**
  82      * longitude parameter
  83      */
  84     const OPTION_LONGITUDE = 'longitude';
  85 
  86     /**
  87      * distance parameter
  88      */
  89     const OPTION_DISTANCE = 'distance';
  90 
  91     /**
  92      * radius parameter
  93      */
  94     const OPTION_RADIUS = 'radius';
  95 
  96     /**
  97      * skip parameter
  98      */
  99     const OPTION_SKIP = 'skip';
 100 
 101     /**
 102      * index parameter
 103      */
 104     const OPTION_INDEX = 'index';
 105 
 106     /**
 107      * limit parameter
 108      */
 109     const OPTION_LIMIT = 'limit';
 110 
 111     /**
 112      * fields
 113      */
 114     const OPTION_FIELDS = 'fields';
 115 
 116     /**
 117      * unique
 118      */
 119     const OPTION_UNIQUE = 'unique';
 120 
 121     /**
 122      * type
 123      */
 124     const OPTION_TYPE = 'type';
 125 
 126     /**
 127      * size option
 128      */
 129     const OPTION_SIZE = 'size';
 130 
 131     /**
 132      * geo index option
 133      */
 134     const OPTION_GEO_INDEX = 'geo';
 135 
 136     /**
 137      * ignoreNull option
 138      */
 139     const OPTION_IGNORE_NULL = 'ignoreNull';
 140 
 141     /**
 142      * constraint option
 143      */
 144     const OPTION_CONSTRAINT = 'constraint';
 145 
 146     /**
 147      * geoJson option
 148      */
 149     const OPTION_GEOJSON = 'geoJson';
 150 
 151     /**
 152      * hash index option
 153      */
 154     const OPTION_HASH_INDEX = 'hash';
 155 
 156     /**
 157      * fulltext index option
 158      */
 159     const OPTION_FULLTEXT_INDEX = 'fulltext';
 160 
 161     /**
 162      * minLength option
 163      */
 164     const OPTION_MIN_LENGTH = 'minLength';
 165 
 166     /**
 167      * skiplist index option
 168      */
 169     const OPTION_SKIPLIST_INDEX = 'skiplist';
 170 
 171     /**
 172      * persistent index option
 173      */
 174     const OPTION_PERSISTENT_INDEX = 'persistent';
 175 
 176     /**
 177      * sparse index option
 178      */
 179     const OPTION_SPARSE = 'sparse';
 180 
 181     /**
 182      * count option
 183      */
 184     const OPTION_COUNT = 'count';
 185 
 186     /**
 187      * query option
 188      */
 189     const OPTION_QUERY = 'query';
 190 
 191     /**
 192      * checksum option
 193      */
 194     const OPTION_CHECKSUM = 'checksum';
 195 
 196     /**
 197      * revision option
 198      */
 199     const OPTION_REVISION = 'revision';
 200 
 201     /**
 202      * properties option
 203      */
 204     const OPTION_PROPERTIES = 'properties';
 205 
 206     /**
 207      * figures option
 208      */
 209     const OPTION_FIGURES = 'figures';
 210 
 211     /**
 212      * load option
 213      */
 214     const OPTION_LOAD = 'load';
 215 
 216     /**
 217      * Creates a new collection on the server
 218      *
 219      * This will add the collection on the server and return its id
 220      * The id is mainly returned for backwards compatibility, but you should use the collection name for any reference to the collection.   *
 221      * This will throw if the collection cannot be created
 222      *
 223      * @throws Exception
 224      *
 225      * @param mixed $collection - collection object to be created on the server or a string with the name
 226      * @param array $options    - an array of options.
 227      *                          <p>Options are :<br>
 228      *                          <li>'type'            - 2 -> normal collection, 3 -> edge-collection</li>
 229      *                          <li>'waitForSync'     -  if set to true, then all removal operations will instantly be synchronised to disk / If this is not specified, then the collection's default sync behavior will be applied.</li>
 230      *                          <li>'journalSize'     -  journalSize value.</li>
 231      *                          <li>'isSystem'        -  false->user collection(default), true->system collection .</li>
 232      *                          <li>'isVolatile'      -  false->persistent collection(default), true->volatile (in-memory) collection .</li>
 233      *                          <li>'numberOfShards'  -  number of shards for the collection.</li>
 234      *                          <li>'shardKeys'       -  list of shard key attributes.</li>
 235      *                          </p>
 236      *
 237      * @return mixed - id of collection created
 238      */
 239     public function create($collection, array $options = [])
 240     {
 241         if (is_string($collection)) {
 242             $name       = $collection;
 243             $collection = new Collection();
 244             $collection->setName($name);
 245             foreach ($options as $key => $value) {
 246                 $collection->{'set' . ucfirst($key)}($value);
 247             }
 248         }
 249         if ($collection->getWaitForSync() === null) {
 250             $collection->setWaitForSync($this->getConnectionOption(ConnectionOptions::OPTION_WAIT_SYNC));
 251         }
 252 
 253         if ($collection->getJournalSize() === null) {
 254             $collection->setJournalSize($this->getConnectionOption(ConnectionOptions::OPTION_JOURNAL_SIZE));
 255         }
 256 
 257         if ($collection->getIsSystem() === null) {
 258             $collection->setIsSystem($this->getConnectionOption(ConnectionOptions::OPTION_IS_SYSTEM));
 259         }
 260 
 261         if ($collection->getIsVolatile() === null) {
 262             $collection->setIsVolatile($this->getConnectionOption(ConnectionOptions::OPTION_IS_VOLATILE));
 263         }
 264 
 265         $type   = $collection->getType() ?: Collection::getDefaultType();
 266         $params = [
 267             Collection::ENTRY_NAME         => $collection->getName(),
 268             Collection::ENTRY_TYPE         => $type,
 269             Collection::ENTRY_WAIT_SYNC    => $collection->getWaitForSync(),
 270             Collection::ENTRY_JOURNAL_SIZE => $collection->getJournalSize(),
 271             Collection::ENTRY_IS_SYSTEM    => $collection->getIsSystem(),
 272             Collection::ENTRY_IS_VOLATILE  => $collection->getIsVolatile(),
 273             Collection::ENTRY_KEY_OPTIONS  => $collection->getKeyOptions(),
 274         ];
 275 
 276         // set extra cluster attributes
 277         if ($collection->getNumberOfShards() !== null) {
 278             $params[Collection::ENTRY_NUMBER_OF_SHARDS] = $collection->getNumberOfShards();
 279         }
 280 
 281         if (is_array($collection->getShardKeys())) {
 282             $params[Collection::ENTRY_SHARD_KEYS] = $collection->getShardKeys();
 283         }
 284 
 285         $response = $this->getConnection()->post(Urls::URL_COLLECTION, $this->json_encode_wrapper($params));
 286 
 287         //    $location = $response->getLocationHeader();
 288         //    if (!$location) {
 289         //      throw new ClientException('Did not find location header in server response');
 290         //    }
 291         $jsonResponse = $response->getJson();
 292         $id           = $jsonResponse['id'];
 293         $collection->setId($id);
 294 
 295         return $id;
 296     }
 297 
 298     /**
 299      * unload option
 300      */
 301     const OPTION_UNLOAD = 'unload';
 302 
 303     /**
 304      * truncate option
 305      */
 306     const OPTION_TRUNCATE = 'truncate';
 307 
 308     /**
 309      * rename option
 310      */
 311     const OPTION_RENAME = 'rename';
 312 
 313 
 314     /**
 315      * exclude system collections
 316      */
 317     const OPTION_EXCLUDE_SYSTEM = 'excludeSystem';
 318 
 319 
 320     /**
 321      * Check if a collection exists
 322      *
 323      * This will call self::get() internally and checks if there
 324      * was an exception thrown which represents an 404 request.
 325      *
 326      * @throws Exception When any other error than a 404 occurs
 327      *
 328      * @param  mixed $collection - collection id as a string or number
 329      *
 330      * @return boolean
 331      */
 332     public function has($collection)
 333     {
 334         $collection = $this->makeCollection($collection);
 335 
 336         try {
 337             // will throw ServerException if entry could not be retrieved
 338             $this->get($collection);
 339 
 340             return true;
 341         } catch (ServerException $e) {
 342             // we are expecting a 404 to return boolean false
 343             if ($e->getCode() === 404) {
 344                 return false;
 345             }
 346 
 347             // just rethrow
 348             throw $e;
 349         }
 350     }
 351 
 352 
 353     /**
 354      * Get the number of documents in a collection
 355      *
 356      * This will throw if the collection cannot be fetched from the server
 357      *
 358      * @throws Exception
 359      *
 360      * @param mixed $collection - collection id as a string or number
 361      *
 362      * @return int - the number of documents in the collection
 363      */
 364     public function count($collection)
 365     {
 366         $collection = $this->makeCollection($collection);
 367         $url        = UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collection, self::OPTION_COUNT]);
 368         $response   = $this->getConnection()->get($url);
 369 
 370         $data  = $response->getJson();
 371         $count = $data[self::OPTION_COUNT];
 372 
 373         return (int) $count;
 374     }
 375 
 376 
 377     /**
 378      * Get information about a collection
 379      *
 380      * This will throw if the collection cannot be fetched from the server
 381      *
 382      * @throws Exception
 383      *
 384      * @param mixed $collection - collection id as a string or number
 385      *
 386      * @return Collection - the collection fetched from the server
 387      */
 388     public function get($collection)
 389     {
 390         $collection = $this->makeCollection($collection);
 391 
 392         $url      = UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collection]);
 393         $response = $this->getConnection()->get($url);
 394 
 395         $data = $response->getJson();
 396 
 397         return Collection::createFromArray($data);
 398     }
 399 
 400 
 401     /**
 402      * Get properties of a collection
 403      *
 404      * This will throw if the collection cannot be fetched from the server
 405      *
 406      * @throws Exception
 407      *
 408      * @param mixed $collection - collection id as a string or number
 409      *
 410      * @return Collection - the collection fetched from the server
 411      */
 412     public function getProperties($collection)
 413     {
 414         $collection = $this->makeCollection($collection);
 415         $url        = UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collection, self::OPTION_PROPERTIES]);
 416         $response   = $this->getConnection()->get($url);
 417 
 418         $data = $response->getJson();
 419 
 420         return Collection::createFromArray($data);
 421     }
 422 
 423 
 424     /**
 425      * Get figures for a collection
 426      *
 427      * This will throw if the collection cannot be fetched from the server
 428      *
 429      * @throws Exception
 430      *
 431      * @param mixed $collection - collection id as a string or number
 432      *
 433      * @return array - the figures for the collection
 434      */
 435     public function figures($collection)
 436     {
 437         $collection = $this->makeCollection($collection);
 438         $url        = UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collection, self::OPTION_FIGURES]);
 439         $response   = $this->getConnection()->get($url);
 440 
 441         $data = $response->getJson();
 442 
 443         return $data[self::OPTION_FIGURES];
 444     }
 445 
 446 
 447     /**
 448      * Calculate a checksum of the collection.
 449      *
 450      * Will calculate a checksum of the meta-data (keys and optionally revision ids)
 451      * and optionally the document data in the collection.
 452      *
 453      * @throws Exception
 454      *
 455      * @param mixed   $collectionId         - collection id as a string or number
 456      * @param boolean $withRevisions        - optional boolean whether or not to include document revision ids
 457      *                                      in the checksum calculation.
 458      * @param boolean $withData             - optional boolean whether or not to include document body data in the
 459      *                                      checksum calculation.
 460      *
 461      * @return array - array containing keys "checksum" and "revision"
 462      */
 463     public function getChecksum($collectionId, $withRevisions = false, $withData = false)
 464     {
 465 
 466         $url      = UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionId, self::OPTION_CHECKSUM]);
 467         $url      = UrlHelper::appendParamsUrl($url, ['withRevisions' => $withRevisions, 'withData' => $withData]);
 468         $response = $this->getConnection()->get($url);
 469 
 470         return $response->getJson();
 471     }
 472 
 473     /**
 474      * Returns the Collections revision ID
 475      *
 476      * The revision id is a server-generated string that clients can use to check whether data in a collection has
 477      * changed since the last revision check.
 478      *
 479      * @throws Exception
 480      *
 481      * @param mixed $collectionId - collection id as a string or number
 482      *
 483      * @return array - containing a key revision
 484      */
 485     public function getRevision($collectionId)
 486     {
 487 
 488         $url      = UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionId, self::OPTION_REVISION]);
 489         $response = $this->getConnection()->get($url);
 490 
 491         return $response->getJson();
 492     }
 493 
 494     /**
 495      * Rename a collection
 496      *
 497      * @throws Exception
 498      *
 499      * @param mixed  $collection - collection id as string or number or collection object
 500      * @param string $name       - new name for collection
 501      *
 502      * @return bool - always true, will throw if there is an error
 503      */
 504     public function rename($collection, $name)
 505     {
 506         $collectionId = $this->getCollectionId($collection);
 507 
 508         if ($this->isValidCollectionId($collectionId)) {
 509             throw new ClientException('Cannot alter a collection without a collection id');
 510         }
 511 
 512         $params = [Collection::ENTRY_NAME => $name];
 513         $this->getConnection()->put(
 514             UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionId, self::OPTION_RENAME]),
 515             $this->json_encode_wrapper($params)
 516         );
 517 
 518         return true;
 519     }
 520 
 521     /**
 522      * Load a collection into the server's memory
 523      *
 524      * This will load the given collection into the server's memory.
 525      *
 526      * @throws Exception
 527      *
 528      * @param mixed $collection - collection id as string or number or collection object
 529      *
 530      * @return HttpResponse - HTTP response object
 531      */
 532     public function load($collection)
 533     {
 534         $collectionId = $this->getCollectionId($collection);
 535 
 536         if ($this->isValidCollectionId($collectionId)) {
 537             throw new ClientException('Cannot alter a collection without a collection id');
 538         }
 539 
 540         $result = $this->getConnection()->put(
 541             UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionId, self::OPTION_LOAD]),
 542             ''
 543         );
 544 
 545         return $result;
 546     }
 547 
 548     /**
 549      * Unload a collection from the server's memory
 550      *
 551      * This will unload the given collection from the server's memory.
 552      *
 553      * @throws Exception
 554      *
 555      * @param mixed $collection - collection id as string or number or collection object
 556      *
 557      * @return HttpResponse - HTTP response object
 558      */
 559     public function unload($collection)
 560     {
 561         $collectionId = $this->getCollectionId($collection);
 562 
 563         if ($this->isValidCollectionId($collectionId)) {
 564             throw new ClientException('Cannot alter a collection without a collection id');
 565         }
 566 
 567         $result = $this->getConnection()->put(
 568             UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionId, self::OPTION_UNLOAD]),
 569             ''
 570         );
 571 
 572         return $result;
 573     }
 574 
 575 
 576     /**
 577      * Truncate a collection
 578      *
 579      * This will remove all documents from the collection but will leave the metadata and indexes intact.
 580      *
 581      * @throws Exception
 582      *
 583      * @param mixed $collection - collection id as string or number or collection object
 584      *
 585      * @return bool - always true, will throw if there is an error
 586      */
 587     public function truncate($collection)
 588     {
 589         $collectionId = $this->getCollectionId($collection);
 590 
 591         if ($this->isValidCollectionId($collectionId)) {
 592             throw new ClientException('Cannot alter a collection without a collection id');
 593         }
 594 
 595         $this->getConnection()->put(
 596             UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionId, self::OPTION_TRUNCATE]),
 597             ''
 598         );
 599 
 600         return true;
 601     }
 602 
 603 
 604     /**
 605      * Drop a collection
 606      *
 607      * @throws Exception
 608      *
 609      * @param mixed $collection - collection id as string or number or collection object
 610      * @param array $options    - an array of options for the drop operation
 611      *
 612      * @return bool - always true, will throw if there is an error
 613      */
 614     public function drop($collection, array $options = [])
 615     {
 616         $collectionName = $this->getCollectionName($collection);
 617 
 618         if ($this->isValidCollectionId($collectionName)) {
 619             throw new ClientException('Cannot alter a collection without a collection id');
 620         }
 621 
 622         $appendix = '';
 623         if (is_array($options) && isset($options['isSystem'])) {
 624             $appendix = '?isSystem=' . UrlHelper::getBoolString($options['isSystem']);
 625         }
 626 
 627         $this->getConnection()->delete(UrlHelper::buildUrl(Urls::URL_COLLECTION, [$collectionName]) . $appendix);
 628 
 629         return true;
 630     }
 631 
 632 
 633     /**
 634      * Checks if the collectionId given, is valid. Returns true if it is, or false if it is not.
 635      *
 636      * @param $collectionId
 637      *
 638      * @return bool
 639      */
 640     public function isValidCollectionId($collectionId)
 641     {
 642         return !$collectionId || !(is_string($collectionId) || is_float($collectionId) || is_int($collectionId));
 643     }
 644 
 645     /**
 646      * Get list of all available collections per default with the collection names as index.
 647      * Returns empty array if none are available.
 648      *
 649      * @param array $options            - optional - an array of options.
 650      *                                  <p>Options are :<br>
 651      *                                  <li>'excludeSystem' -   With a value of true, all system collections will be excluded from the response.</li>
 652      *                                  <li>'keys' -  With a value of "collections", the index of the resulting array is numerical,
 653      *                                  With a value of "names", the index of the resulting array are the collection names.</li>
 654      *                                  </p>
 655      *
 656      * @return array
 657      * @throws \triagens\ArangoDb\Exception
 658      * @throws \triagens\ArangoDb\ClientException
 659      */
 660     public function getAllCollections(array $options = [])
 661     {
 662         $options = array_merge(['excludeSystem' => false, 'keys' => 'result'], $options);
 663         $params  = [];
 664         if ($options['excludeSystem'] === true) {
 665             $params[self::OPTION_EXCLUDE_SYSTEM] = true;
 666         }
 667         $url      = UrlHelper::appendParamsUrl(Urls::URL_COLLECTION, $params);
 668         $response = $this->getConnection()->get(UrlHelper::buildUrl($url, []));
 669         $response = $response->getJson();
 670         if (isset($response[$options['keys']])) {
 671             $result = [];
 672             foreach ($response[$options['keys']] as $collection) {
 673                 $result[$collection['name']] = $collection;
 674             }
 675 
 676             return $result;
 677         }
 678 
 679         return $response;
 680     }
 681 
 682 
 683     /**
 684      * Gets the collectionId from the given collectionObject or string/integer
 685      *
 686      * @param mixed $collection
 687      *
 688      * @return mixed
 689      */
 690     public function getCollectionId($collection)
 691     {
 692         if ($collection instanceof Collection) {
 693             $collectionId = $collection->getId();
 694 
 695             return $collectionId;
 696         } else {
 697             $collectionId = $collection;
 698 
 699             return $collectionId;
 700         }
 701     }
 702 
 703 
 704     /**
 705      * Gets the collectionId from the given collectionObject or string/integer
 706      *
 707      * @param mixed $collection
 708      *
 709      * @return mixed
 710      */
 711     public function getCollectionName($collection)
 712     {
 713         if ($collection instanceof Collection) {
 714             $collectionId = $collection->getName();
 715 
 716             return $collectionId;
 717         } else {
 718             $collectionId = $collection;
 719 
 720             return $collectionId;
 721         }
 722     }
 723 
 724 
 725     /**
 726      * Import documents from a file
 727      *
 728      * This will throw on all errors except insertion errors
 729      *
 730      * @throws Exception
 731      *
 732      * @param mixed $collectionId   - collection id as string or number
 733      * @param mixed $importFileName - The filename that holds the import data.
 734      * @param array $options        - optional - an array of options.
 735      *                              <p>Options are :<br>
 736      *                              'type' -  if type is not set or it's set to '' or null, the Header-Value format must be provided in the import file.<br>
 737      *                              <p>
 738      *                              <li>                       if set to 'documents', then the file's content must have its documents line by line. Each line will be interpreted as a document.</li>
 739      *                              <li>                       if set to 'array' then the file's content must provide the documents as a list of documents instead of the above line by line.</li>
 740      *                              <br>
 741      *                              More info on how the import functionality works: <a href ="https://github.com/triAGENS/ArangoDB/wiki/HttpImport">https://github.com/triAGENS/ArangoDB/wiki/HttpImport</a>
 742      *                              </p>
 743      *                              <br>
 744      *                              </li>
 745      *                              <li>'createCollection' - If true, create the collection if it does not exist. Defaults to false </li>
 746      *                              </p>
 747      *
 748      * @return array - returns an array with the server's response data from the import command
 749      */
 750     public function importFromFile(
 751         $collectionId,
 752         $importFileName,
 753         array $options = []
 754     )
 755     {
 756 
 757         $contents = file_get_contents($importFileName);
 758         if ($contents === false) {
 759             throw new ClientException('Input file "' . $importFileName . '" could not be found.');
 760         }
 761 
 762         return $this->import($collectionId, $contents, $options);
 763     }
 764 
 765 
 766     /**
 767      * Import documents into a collection
 768      *
 769      * This will throw on all errors except insertion errors
 770      *
 771      *
 772      * @param              $collection   mixed $collection - collection id as string or number
 773      * @param string|array $importData   - The data to import. This can be a string holding the data according to the type of import, or an array of documents
 774      * @param array        $options      - optional - an array of options.
 775      *                                   <p>Options are :<br>
 776      *                                   <li>
 777      *                                   'type' -  if type is not set or it's set to '' or null, the Header-Value format must be provided in the import file.<br>
 778      *                                   <p>
 779      *                                   <li>                       if set to 'documents', then the file's content must have its documents line by line. Each line will be interpreted as a document.</li>
 780      *                                   <li>                       if set to 'array' then the file's content must provide the documents as a list of documents instead of the above line by line.</li>
 781      *                                   <br>
 782      *                                   More info on how the import functionality works: <a href ="https://github.com/triAGENS/ArangoDB/wiki/HttpImport">https://github.com/triAGENS/ArangoDB/wiki/HttpImport</a>
 783      *                                   </p>
 784      *                                   <br>
 785      *
 786      *                                   </li>
 787      *                                   <li>'createCollection' - If true, create the collection if it does not exist. Defaults to false </li>
 788      *                                   </p>
 789      *
 790      * @return array
 791      * @throws \triagens\ArangoDb\Exception
 792      * @throws \triagens\ArangoDb\ClientException
 793      */
 794     public function import(
 795         $collection,
 796         $importData,
 797         array $options = []
 798     )
 799     {
 800         $collection = $this->makeCollection($collection);
 801 
 802         $tmpContent = '';
 803         if (is_array($importData)) {
 804             foreach ($importData as $document) {
 805                 /** @var $document Document */
 806                 $tmpContent .= $document->toJson() . "\r\n";
 807             }
 808             $importData = $tmpContent;
 809             unset($tmpContent);
 810             $options['type'] = 'documents';
 811         }
 812 
 813         $this->createCollectionIfOptions($collection, $options);
 814 
 815         $params = [
 816             self::OPTION_COLLECTION => $collection
 817         ];
 818 
 819         if (array_key_exists('type', $options)) {
 820             switch ($options['type']) {
 821                 case 'documents':
 822                     $params[self::OPTION_TYPE] = 'documents';
 823                     break;
 824                 case 'array':
 825                     $params[self::OPTION_TYPE] = 'array';
 826                     break;
 827             }
 828         }
 829 
 830         $url = UrlHelper::appendParamsUrl(Urls::URL_IMPORT, $params);
 831 
 832         $response = $this->getConnection()->post($url, $importData);
 833 
 834         return $response->getJson();
 835     }
 836 
 837 
 838     /**
 839      * Create a hash index
 840      *
 841      * @param string  $collectionId - the collection id
 842      * @param array   $fields       - an array of fields
 843      * @param boolean $unique       - whether the values in the index should be unique or not
 844      * @param boolean $sparse       - whether the index should be sparse
 845      *
 846      * @link https://docs.arangodb.com/HTTP/Indexes/Hash.html
 847      *
 848      * @return array - server response of the created index
 849      * @throws \triagens\ArangoDb\Exception
 850      */
 851     public function createHashIndex($collectionId, array $fields, $unique = null, $sparse = null)
 852     {
 853         $indexOptions = [];
 854 
 855         if ($unique) {
 856             $indexOptions[self::OPTION_UNIQUE] = (bool) $unique;
 857         }
 858         if ($sparse) {
 859             $indexOptions[self::OPTION_SPARSE] = (bool) $sparse;
 860         }
 861 
 862         return $this->index($collectionId, self::OPTION_HASH_INDEX, $fields, null, $indexOptions);
 863     }
 864 
 865     /**
 866      * Create a fulltext index
 867      *
 868      * @param string $collectionId - the collection id
 869      * @param array  $fields       - an array of fields
 870      * @param int    $minLength    - the minimum length of words to index
 871      *
 872      * @link https://docs.arangodb.com/HTTP/Indexes/Fulltext.html
 873      *
 874      * @return array - server response of the created index
 875      * @throws \triagens\ArangoDb\Exception
 876      */
 877     public function createFulltextIndex($collectionId, array $fields, $minLength = null)
 878     {
 879         $indexOptions = [];
 880 
 881         if ($minLength) {
 882             $indexOptions[self::OPTION_MIN_LENGTH] = $minLength;
 883         }
 884 
 885         return $this->index($collectionId, self::OPTION_FULLTEXT_INDEX, $fields, null, $indexOptions);
 886     }
 887 
 888     /**
 889      * Create a skip-list index
 890      *
 891      * @param string $collectionId - the collection id
 892      * @param array  $fields       - an array of fields
 893      * @param bool   $unique       - whether the index is unique or not
 894      * @param bool   $sparse       - whether the index should be sparse
 895      *
 896      * @link https://docs.arangodb.com/HTTP/Indexes/Skiplist.html
 897      *
 898      * @return array - server response of the created index
 899      * @throws \triagens\ArangoDb\Exception
 900      */
 901     public function createSkipListIndex($collectionId, array $fields, $unique = null, $sparse = null)
 902     {
 903         $indexOptions = [];
 904 
 905         if ($unique) {
 906             $indexOptions[self::OPTION_UNIQUE] = (bool) $unique;
 907         }
 908         if ($sparse) {
 909             $indexOptions[self::OPTION_SPARSE] = (bool) $sparse;
 910         }
 911 
 912         return $this->index($collectionId, self::OPTION_SKIPLIST_INDEX, $fields, null, $indexOptions);
 913     }
 914 
 915     /**
 916      * Create a persistent index
 917      *
 918      * @param string $collectionId - the collection id
 919      * @param array  $fields       - an array of fields
 920      * @param bool   $unique       - whether the index is unique or not
 921      * @param bool   $sparse       - whether the index should be sparse
 922      *
 923      * @link https://docs.arangodb.com/HTTP/Indexes/Persistent.html
 924      *
 925      * @return array - server response of the created index
 926      * @throws \triagens\ArangoDb\Exception
 927      */
 928     public function createPersistentIndex($collectionId, array $fields, $unique = null, $sparse = null)
 929     {
 930         $indexOptions = [];
 931 
 932         if ($unique) {
 933             $indexOptions[self::OPTION_UNIQUE] = (bool) $unique;
 934         }
 935         if ($sparse) {
 936             $indexOptions[self::OPTION_SPARSE] = (bool) $sparse;
 937         }
 938 
 939         return $this->index($collectionId, self::OPTION_PERSISTENT_INDEX, $fields, null, $indexOptions);
 940     }
 941 
 942     /**
 943      * Create a geo index
 944      *
 945      * @param string  $collectionId - the collection id
 946      * @param array   $fields       - an array of fields
 947      * @param boolean $geoJson      - whether to use geoJson or not
 948      * @param boolean $constraint   - whether this is a constraint or not
 949      * @param boolean $ignoreNull   - whether to ignore null
 950      *
 951      * @link https://docs.arangodb.com/HTTP/Indexes/Geo.html
 952      *
 953      * @return array - server response of the created index
 954      * @throws \triagens\ArangoDb\Exception
 955      */
 956     public function createGeoIndex($collectionId, array $fields, $geoJson = null, $constraint = null, $ignoreNull = null)
 957     {
 958         $indexOptions = [];
 959 
 960         if ($geoJson) {
 961             $indexOptions[self::OPTION_GEOJSON] = (bool) $geoJson;
 962         }
 963 
 964         if ($constraint) {
 965             $indexOptions[self::OPTION_CONSTRAINT] = (bool) $constraint;
 966         }
 967 
 968         if ($ignoreNull) {
 969             $indexOptions[self::OPTION_IGNORE_NULL] = $ignoreNull;
 970         }
 971 
 972         return $this->index($collectionId, self::OPTION_GEO_INDEX, $fields, null, $indexOptions);
 973     }
 974 
 975     /**
 976      * Creates an index on a collection on the server
 977      *
 978      * This will create an index on the collection on the server and return its id
 979      *
 980      * This will throw if the index cannot be created
 981      *
 982      * @throws Exception
 983      *
 984      * @param mixed  $collectionId - The id of the collection where the index is to be created
 985      * @param string $type         - index type: hash, skiplist, geo, fulltext, or persistent
 986      * @param array  $attributes   - an array of attributes that can be defined like array('a') or array('a', 'b.c')
 987      * @param bool   $unique       - true/false to create a unique index
 988      * @param array  $indexOptions - an associative array of options for the index like array('geoJson' => true, 'sparse' => false)
 989      *
 990      * @return array - server response of the created index
 991      */
 992     public function index($collectionId, $type = '', array $attributes = [], $unique = false, array $indexOptions = [])
 993     {
 994 
 995         $urlParams  = [self::OPTION_COLLECTION => $collectionId];
 996         $bodyParams = [
 997             self::OPTION_TYPE   => $type,
 998             self::OPTION_FIELDS => $attributes,
 999         ];
1000 
1001         if ($unique !== null) {
1002             $bodyParams[self::OPTION_UNIQUE] = (bool) $unique;
1003         }
1004 
1005         $bodyParams = array_merge($bodyParams, $indexOptions);
1006 
1007         $url      = UrlHelper::appendParamsUrl(Urls::URL_INDEX, $urlParams);
1008         $response = $this->getConnection()->post($url, $this->json_encode_wrapper($bodyParams));
1009 
1010         $httpCode = $response->getHttpCode();
1011         switch ($httpCode) {
1012             case 404:
1013                 throw new ClientException('Collection-identifier is unknown');
1014 
1015                 break;
1016             case 400:
1017                 throw new ClientException('cannot create unique index due to documents violating uniqueness');
1018                 break;
1019         }
1020 
1021         return $response->getJson();
1022     }
1023 
1024 
1025     /**
1026      * Get the information about an index in a collection
1027      *
1028      * @param string $collection - the id of the collection
1029      * @param string $indexId    - the id of the index
1030      *
1031      * @return array
1032      * @throws \triagens\ArangoDb\Exception
1033      * @throws \triagens\ArangoDb\ClientException
1034      */
1035     public function getIndex($collection, $indexId)
1036     {
1037         $url      = UrlHelper::buildUrl(Urls::URL_INDEX, [$collection, $indexId]);
1038         $response = $this->getConnection()->get($url);
1039 
1040         return $response->getJson();
1041     }
1042 
1043 
1044     /**
1045      * Get indexes of a collection
1046      *
1047      * This will throw if the collection cannot be fetched from the server
1048      *
1049      * @throws Exception
1050      *
1051      * @param mixed $collectionId - collection id as a string or number
1052      *
1053      * @return array $data - the indexes result-set from the server
1054      */
1055     public function getIndexes($collectionId)
1056     {
1057         $urlParams = [self::OPTION_COLLECTION => $collectionId];
1058         $url       = UrlHelper::appendParamsUrl(Urls::URL_INDEX, $urlParams);
1059         $response  = $this->getConnection()->get($url);
1060 
1061         return $response->getJson();
1062     }
1063 
1064     /**
1065      * Drop an index
1066      *
1067      * @throws Exception
1068      *
1069      * @param mixed $indexHandle - index handle (collection name / index id)
1070      *
1071      * @return bool - always true, will throw if there is an error
1072      */
1073     public function dropIndex($indexHandle)
1074     {
1075         $handle = explode('/', $indexHandle);
1076         $this->getConnection()->delete(UrlHelper::buildUrl(Urls::URL_INDEX, [$handle[0], $handle[1]]));
1077 
1078         return true;
1079     }
1080 
1081     /**
1082      * Get a random document from the collection.
1083      *
1084      * This will throw if the document cannot be fetched from the server
1085      *
1086      *
1087      * @throws Exception
1088      *
1089      * @param mixed $collectionId - collection id as string or number
1090      *
1091      * @return Document - the document fetched from the server
1092      * @since 1.2
1093      */
1094     public function any($collectionId)
1095     {
1096 
1097         $data = [
1098             self::OPTION_COLLECTION => $collectionId,
1099         ];
1100 
1101         $response = $this->getConnection()->put(Urls::URL_ANY, $this->json_encode_wrapper($data));
1102         $data     = $response->getJson();
1103 
1104         if ($data['document']) {
1105             return Document::createFromArray($data['document']);
1106         } else {
1107             return null;
1108         }
1109     }
1110 
1111 
1112     /**
1113      * Returns all documents of a collection
1114      *
1115      * @param mixed $collectionId     - collection id as string or number
1116      * @param array $options          - optional array of options.
1117      *                                <p>Options are :<br>
1118      *                                <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1119      *                                <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1120      *                                <p>
1121      *                                This is actually the same as setting hidden attributes using setHiddenAttributes() on a document.<br>
1122      *                                The difference is, that if you're returning a result set of documents, the getAll() is already called<br>
1123      *                                and the hidden attributes would not be applied to the attributes.<br>
1124      *                                </p>
1125      *
1126      * <li>'batchSize' - can optionally be used to tell the server to limit the number of results to be transferred in one batch</li>
1127      * <li>'skip'      -  Optional, The number of documents to skip in the query.</li>
1128      * <li>'limit'     -  Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1129      * </li>
1130      * </p>
1131      *
1132      * @return Cursor - documents
1133      * @throws \triagens\ArangoDb\Exception
1134      * @throws \triagens\ArangoDb\ClientException
1135      */
1136     public function all($collectionId, array $options = [])
1137     {
1138         $body = [
1139             self::OPTION_COLLECTION => $collectionId,
1140         ];
1141 
1142         $body = $this->includeOptionsInBody(
1143             $options,
1144             $body,
1145             [
1146                 self::OPTION_LIMIT => null,
1147                 self::OPTION_SKIP  => null,
1148             ]
1149         );
1150 
1151         $response = $this->getConnection()->put(Urls::URL_ALL, $this->json_encode_wrapper($body));
1152 
1153         return new Cursor($this->getConnection(), $response->getJson(), $options);
1154     }
1155 
1156 
1157     /**
1158      * Get the list of all documents' ids from a collection
1159      *
1160      * This will throw if the list cannot be fetched from the server
1161      *
1162      * @throws Exception
1163      *
1164      * @param mixed $collection - collection id as string or number
1165      *
1166      * @return array - ids of documents in the collection
1167      */
1168     public function getAllIds($collection)
1169     {
1170         $params   = [
1171             self::OPTION_COLLECTION => $this->makeCollection($collection)
1172         ];
1173         $response = $this->getConnection()->put(Urls::URL_ALL_KEYS, $this->json_encode_wrapper($params));
1174 
1175         $data = $response->getJson();
1176         if (!isset($data[Cursor::ENTRY_RESULT])) {
1177             throw new ClientException('Got an invalid document list from the server');
1178         }
1179 
1180         $cursor = new Cursor($this->getConnection(), $response->getJson(), []);
1181         $ids    = [];
1182         foreach ($cursor->getAll() as $location) {
1183             $ids[] = UrlHelper::getDocumentIdFromLocation($location);
1184         }
1185 
1186         return $ids;
1187     }
1188 
1189     /**
1190      * Get document(s) by specifying an example
1191      *
1192      * This will throw if the list cannot be fetched from the server
1193      *
1194      *
1195      * @throws Exception
1196      *
1197      * @param mixed $collectionId      - collection id as string or number
1198      * @param mixed $document          - the example document as a Document object or an array
1199      * @param array $options           - optional, prior to v1.0.0 this was a boolean value for sanitize, since v1.0.0 it's an array of options.
1200      *                                 <p>Options are :<br>
1201      *                                 <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1202      *                                 <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1203      *                                 <p>
1204      *                                 This is actually the same as setting hidden attributes using setHiddenAttributes() on a document. <br>
1205      *                                 The difference is, that if you're returning a result set of documents, the getAll() is already called <br>
1206      *                                 and the hidden attributes would not be applied to the attributes.<br>
1207      *                                 </p>
1208      *                                 </li>
1209      *                                 <li>'batchSize' - can optionally be used to tell the server to limit the number of results to be transferred in one batch</li>
1210      *                                 <li>'skip'      - Optional, The number of documents to skip in the query.</li>
1211      *                                 <li>'limit'     - Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1212      *                                 </p>
1213      *
1214      * @return cursor - Returns a cursor containing the result
1215      */
1216     public function byExample($collectionId, $document, array $options = [])
1217     {
1218         if (is_array($document)) {
1219             $document = Document::createFromArray($document, $options);
1220         }
1221 
1222         if (!($document instanceof Document)) {
1223             throw new ClientException('Invalid example document specification');
1224         }
1225 
1226         $body = [
1227             self::OPTION_COLLECTION => $collectionId,
1228             self::OPTION_EXAMPLE    => $document->getAllAsObject(['_ignoreHiddenAttributes' => true])
1229         ];
1230 
1231         $body = $this->includeOptionsInBody(
1232             $options,
1233             $body,
1234             [
1235                 ConnectionOptions::OPTION_BATCHSIZE => $this->getConnectionOption(
1236                     ConnectionOptions::OPTION_BATCHSIZE
1237                 ),
1238                 self::OPTION_LIMIT                  => null,
1239                 self::OPTION_SKIP                   => null,
1240             ]
1241         );
1242 
1243         $response = $this->getConnection()->put(Urls::URL_EXAMPLE, $this->json_encode_wrapper($body));
1244 
1245         $options['isNew'] = false;
1246 
1247         return new Cursor($this->getConnection(), $response->getJson(), $options);
1248     }
1249 
1250     /**
1251      * Get the first document matching a given example.
1252      *
1253      * This will throw if the document cannot be fetched from the server
1254      *
1255      *
1256      * @throws Exception
1257      *
1258      * @param mixed $collectionId      - collection id as string or number
1259      * @param mixed $document          - the example document as a Document object or an array
1260      * @param array $options           - optional, an array of options.
1261      *                                 <p>Options are :<br>
1262      *                                 <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1263      *                                 <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1264      *                                 <p>
1265      *                                 This is actually the same as setting hidden attributes using setHiddenAttributes() on a document. <br>
1266      *                                 The difference is, that if you're returning a result set of documents, the getAll() is already called <br>
1267      *                                 and the hidden attributes would not be applied to the attributes.<br>
1268      *                                 </p>
1269      *                                 </li>
1270      *                                 </p>
1271      *
1272      * @return Document - the document fetched from the server
1273      * @since 1.2
1274      */
1275     public function firstExample($collectionId, $document, array $options = [])
1276     {
1277         if (is_array($document)) {
1278             $document = Document::createFromArray($document, $options);
1279         }
1280 
1281         if (!($document instanceof Document)) {
1282             throw new ClientException('Invalid example document specification');
1283         }
1284 
1285         $data = [
1286             self::OPTION_COLLECTION => $collectionId,
1287             self::OPTION_EXAMPLE    => $document->getAll(['_ignoreHiddenAttributes' => true])
1288         ];
1289 
1290         $response = $this->getConnection()->put(Urls::URL_FIRST_EXAMPLE, $this->json_encode_wrapper($data));
1291         $data     = $response->getJson();
1292 
1293         $options['_isNew'] = false;
1294 
1295         return Document::createFromArray($data['document'], $options);
1296     }
1297 
1298 
1299     /**
1300      * Get document(s) by a fulltext query
1301      *
1302      * This will find all documents from the collection that match the fulltext query specified in query.
1303      * In order to use the fulltext operator, a fulltext index must be defined for the collection and the specified attribute.
1304      *
1305      *
1306      * @throws Exception
1307      *
1308      * @param mixed $collection        - collection id as string or number
1309      * @param mixed $attribute         - The attribute that contains the texts.
1310      * @param mixed $query             - The fulltext query.
1311      * @param array $options           - optional, prior to v1.0.0 this was a boolean value for sanitize, since v1.0.0 it's an array of options.
1312      *                                 <p>Options are :<br>
1313      *                                 <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1314      *                                 <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1315      *                                 <p>
1316      *                                 This is actually the same as setting hidden attributes using setHiddenAttributes() on a document. <br>
1317      *                                 The difference is, that if you're returning a result set of documents, the getAll() is already called <br>
1318      *                                 and the hidden attributes would not be applied to the attributes.<br>
1319      *                                 </p>
1320      *                                 </li>
1321      *                                 <li>'batchSize' - can optionally be used to tell the server to limit the number of results to be transferred in one batch</li>
1322      *                                 <li>'skip'      - Optional, The number of documents to skip in the query.</li>
1323      *                                 <li>'limit'     - Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1324      *                                 <li>'index'     - If given, the identifier of the fulltext-index to use.</li>
1325      *                                 </p>
1326      *
1327      * @return cursor - Returns a cursor containing the result
1328      */
1329     public function fulltext($collection, $attribute, $query, array $options = [])
1330     {
1331         $body = [
1332             self::OPTION_COLLECTION => $collection,
1333             self::OPTION_ATTRIBUTE  => $attribute,
1334             self::OPTION_QUERY      => $query,
1335         ];
1336 
1337         $body = $this->includeOptionsInBody(
1338             $options,
1339             $body,
1340             [
1341                 ConnectionOptions::OPTION_BATCHSIZE => $this->getConnectionOption(
1342                     ConnectionOptions::OPTION_BATCHSIZE
1343                 ),
1344                 self::OPTION_LIMIT                  => null,
1345                 self::OPTION_SKIP                   => null,
1346                 self::OPTION_INDEX                  => null,
1347             ]
1348         );
1349 
1350         $response = $this->getConnection()->put(Urls::URL_FULLTEXT, $this->json_encode_wrapper($body));
1351 
1352         $options['isNew'] = false;
1353 
1354         return new Cursor($this->getConnection(), $response->getJson(), $options);
1355     }
1356 
1357 
1358     /**
1359      * Update document(s) matching a given example
1360      *
1361      * This will update the document(s) on the server
1362      *
1363      * This will throw if the document cannot be updated
1364      *
1365      * @throws Exception
1366      *
1367      * @param mixed $collectionId - collection id as string or number
1368      * @param mixed $example      - the example document as a Document object or an array
1369      * @param mixed $newValue     - patch document or array which contains the attributes and values to be updated
1370      * @param mixed $options      - optional, array of options (see below) or the boolean value for $policy (for compatibility prior to version 1.1 of this method)
1371      *                            <p>Options are :
1372      *                            <li>'keepNull'    - can be used to instruct ArangoDB to delete existing attributes instead setting their values to null. Defaults to true (keep attributes when set to null)</li>
1373      *                            <li>'waitForSync' - can be used to force synchronisation of the document update operation to disk even in case that the waitForSync flag had been disabled for the entire collection</li>
1374      *                            <li>'limit'       - can be used set a limit on how many documents to update at most. If limit is specified but is less than the number of documents in the collection, it is undefined which of the documents will be updated.</li>
1375      *                            </p>
1376      *
1377      * @return bool - always true, will throw if there is an error
1378      * @since 1.2
1379      */
1380     public function updateByExample($collectionId, $example, $newValue, array $options = [])
1381     {
1382         if (is_array($example)) {
1383             $example = Document::createFromArray($example);
1384         }
1385 
1386         if (is_array($newValue)) {
1387             $newValue = Document::createFromArray($newValue);
1388         }
1389 
1390         $body = [
1391             self::OPTION_COLLECTION => $collectionId,
1392             self::OPTION_EXAMPLE    => $example->getAllAsObject(['_ignoreHiddenAttributes' => true]),
1393             self::OPTION_NEW_VALUE  => $newValue->getAllAsObject(['_ignoreHiddenAttributes' => true])
1394         ];
1395 
1396         $body = $this->includeOptionsInBody(
1397             $options,
1398             $body,
1399             [
1400                 ConnectionOptions::OPTION_WAIT_SYNC => $this->getConnectionOption(
1401                     ConnectionOptions::OPTION_WAIT_SYNC
1402                 ),
1403                 'keepNull'                          => true,
1404                 self::OPTION_LIMIT                  => null,
1405             ]
1406         );
1407 
1408         $response = $this->getConnection()->put(Urls::URL_UPDATE_BY_EXAMPLE, $this->json_encode_wrapper($body));
1409 
1410         $responseArray = $response->getJson();
1411 
1412         if ($responseArray['error'] === true) {
1413             throw new ClientException('Invalid example document specification');
1414         }
1415 
1416         return $responseArray['updated'];
1417     }
1418 
1419 
1420     /**
1421      * Replace document(s) matching a given example
1422      *
1423      * This will replace the document(s) on the server
1424      *
1425      * This will throw if the document cannot be replaced
1426      *
1427      * @throws Exception
1428      *
1429      * @param mixed $collectionId - collection id as string or number
1430      * @param mixed $example      - the example document as a Document object or an array
1431      * @param mixed $newValue     - patch document or array which contains the attributes and values to be replaced
1432      * @param mixed $options      - optional, array of options (see below) or the boolean value for $policy (for compatibility prior to version 1.1 of this method)
1433      *                            <p>Options are :
1434      *                            <li>'keepNull'    - can be used to instruct ArangoDB to delete existing attributes instead setting their values to null. Defaults to true (keep attributes when set to null)</li>
1435      *                            <li>'waitForSync' - can be used to force synchronisation of the document replace operation to disk even in case that the waitForSync flag had been disabled for the entire collection</li>
1436      *                            <li>'limit'       - can be used set a limit on how many documents to replace at most. If limit is specified but is less than the number of documents in the collection, it is undefined which of the documents will be replaced.</li>
1437      *                            </p>
1438      *
1439      * @return bool - always true, will throw if there is an error
1440      * @since 1.2
1441      */
1442     public function replaceByExample($collectionId, $example, $newValue, array $options = [])
1443     {
1444         if (is_array($example)) {
1445             $example = Document::createFromArray($example);
1446         }
1447 
1448         if (is_array($newValue)) {
1449             $newValue = Document::createFromArray($newValue);
1450         }
1451 
1452         $body = [
1453             self::OPTION_COLLECTION => $collectionId,
1454             self::OPTION_EXAMPLE    => $example->getAllAsObject(['_ignoreHiddenAttributes' => true]),
1455             self::OPTION_NEW_VALUE  => $newValue->getAllAsObject(['_ignoreHiddenAttributes' => true])
1456         ];
1457 
1458         $body = $this->includeOptionsInBody(
1459             $options,
1460             $body,
1461             [
1462                 ConnectionOptions::OPTION_WAIT_SYNC => $this->getConnectionOption(
1463                     ConnectionOptions::OPTION_WAIT_SYNC
1464                 ),
1465                 'keepNull'                          => true,
1466                 self::OPTION_LIMIT                  => null,
1467             ]
1468         );
1469 
1470         $response = $this->getConnection()->put(Urls::URL_REPLACE_BY_EXAMPLE, $this->json_encode_wrapper($body));
1471 
1472         $responseArray = $response->getJson();
1473 
1474         if ($responseArray['error'] === true) {
1475             throw new ClientException('Invalid example document specification');
1476         }
1477 
1478         return $responseArray['replaced'];
1479     }
1480 
1481 
1482     /**
1483      * Remove document(s) by specifying an example
1484      *
1485      * This will throw on any error
1486      *
1487      * @throws Exception
1488      *
1489      * @param mixed $collectionId      - collection id as string or number
1490      * @param mixed $document          - the example document as a Document object or an array
1491      * @param array $options           - optional - an array of options.
1492      *                                 <p>Options are :<br>
1493      *                                 <li>
1494      *                                 'waitForSync' -  if set to true, then all removal operations will instantly be synchronised to disk.<br>
1495      *                                 If this is not specified, then the collection's default sync behavior will be applied.
1496      *                                 </li>
1497      *                                 </p>
1498      *                                 <li>'limit' -  Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1499      *
1500      * @return int - number of documents that were deleted
1501      *
1502      * @since 1.2
1503      */
1504     public function removeByExample($collectionId, $document, array $options = [])
1505     {
1506         if (is_array($document)) {
1507             $document = Document::createFromArray($document, $options);
1508         }
1509 
1510         if (!($document instanceof Document)) {
1511             throw new ClientException('Invalid example document specification');
1512         }
1513 
1514         $body = [
1515             self::OPTION_COLLECTION => $collectionId,
1516             self::OPTION_EXAMPLE    => $document->getAllAsObject(['_ignoreHiddenAttributes' => true])
1517         ];
1518 
1519         $body = $this->includeOptionsInBody(
1520             $options,
1521             $body,
1522             [
1523                 ConnectionOptions::OPTION_WAIT_SYNC => $this->getConnectionOption(
1524                     ConnectionOptions::OPTION_WAIT_SYNC
1525                 ),
1526                 self::OPTION_LIMIT                  => null,
1527             ]
1528         );
1529 
1530         $response = $this->getConnection()->put(Urls::URL_REMOVE_BY_EXAMPLE, $this->json_encode_wrapper($body));
1531 
1532         $responseArray = $response->getJson();
1533 
1534         if ($responseArray['error'] === true) {
1535             throw new ClientException('Invalid example document specification');
1536         }
1537 
1538         return $responseArray['deleted'];
1539     }
1540 
1541     /**
1542      * Remove document(s) by specifying an array of keys
1543      *
1544      * This will throw on any error
1545      *
1546      * @throws Exception
1547      *
1548      * @param mixed $collectionId      - collection id as string or number
1549      * @param array $keys              - array of document keys
1550      * @param array $options           - optional - an array of options.
1551      *                                 <p>Options are :<br>
1552      *                                 <li>
1553      *                                 'waitForSync' -  if set to true, then all removal operations will instantly be synchronised to disk.<br>
1554      *                                 If this is not specified, then the collection's default sync behavior will be applied.
1555      *                                 </li>
1556      *                                 </p>
1557      *
1558      * @return array - an array containing an attribute 'removed' with the number of documents that were deleted, an an array 'ignored' with the number of not removed keys/documents
1559      *
1560      * @since 2.6
1561      */
1562     public function removeByKeys($collectionId, array $keys, array $options = [])
1563     {
1564         $body = [
1565             self::OPTION_COLLECTION => $collectionId,
1566             self::OPTION_KEYS       => $keys
1567         ];
1568 
1569         $body = $this->includeOptionsInBody(
1570             $options,
1571             $body,
1572             [
1573                 ConnectionOptions::OPTION_WAIT_SYNC => $this->getConnectionOption(
1574                     ConnectionOptions::OPTION_WAIT_SYNC
1575                 )
1576             ]
1577         );
1578 
1579         $response = $this->getConnection()->put(Urls::URL_REMOVE_BY_KEYS, $this->json_encode_wrapper($body));
1580 
1581         $responseArray = $response->getJson();
1582 
1583         return [
1584             'removed' => $responseArray['removed'],
1585             'ignored' => $responseArray['ignored']
1586         ];
1587     }
1588 
1589 
1590     /**
1591      * Bulk lookup documents by specifying an array of keys
1592      *
1593      * This will throw on any error
1594      *
1595      * @throws Exception
1596      *
1597      * @param mixed $collectionId        - collection id as string or number
1598      * @param array $keys                - array of document keys
1599      * @param array $options             - optional array of options.
1600      *                                   <p>Options are :<br>
1601      *                                   <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1602      *                                   <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1603      *                                   </p>
1604      *
1605      * @return array - an array containing all documents found for the keys specified.
1606      *                 note that if for a given key not document is found, it will not be returned nor will the document's non-existence be reported.
1607      *
1608      * @since 2.6
1609      */
1610     public function lookupByKeys($collectionId, array $keys, array $options = [])
1611     {
1612         $body = [
1613             self::OPTION_COLLECTION => $collectionId,
1614             self::OPTION_KEYS       => $keys
1615         ];
1616 
1617         $response = $this->getConnection()->put(Urls::URL_LOOKUP_BY_KEYS, $this->json_encode_wrapper($body));
1618 
1619         $responseArray = $response->getJson();
1620 
1621         $result = [];
1622         foreach ($responseArray['documents'] as $document) {
1623             $result[] = Document::createFromArray($document, $options);
1624         }
1625 
1626         return $result;
1627     }
1628 
1629 
1630     /**
1631      * Get document(s) by specifying range
1632      *
1633      * This will throw if the list cannot be fetched from the server
1634      *
1635      *
1636      * @throws Exception
1637      *
1638      * @param mixed  $collectionId    - collection id as string or number
1639      * @param string $attribute       - the attribute path , like 'a', 'a.b', etc...
1640      * @param mixed  $left            - The lower bound.
1641      * @param mixed  $right           - The upper bound.
1642      * @param array  $options         - optional array of options.
1643      *                                <p>Options are :<br>
1644      *                                <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1645      *                                <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1646      *                                <p>
1647      *                                This is actually the same as setting hidden attributes using setHiddenAttributes() on a document.<br>
1648      *                                The difference is, that if you're returning a result set of documents, the getAll() is already called<br>
1649      *                                and the hidden attributes would not be applied to the attributes.<br>
1650      *                                </p>
1651      *
1652      *                                <li>'closed'    - If true, use interval including left and right, otherwise exclude right, but include left.
1653      *                                <li>'batchSize' - can optionally be used to tell the server to limit the number of results to be transferred in one batch</li>
1654      *                                <li>'skip'      -  Optional, The number of documents to skip in the query.</li>
1655      *                                <li>'limit'     -  Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1656      *                                </li>
1657      *                                </p>
1658      *
1659      * @return Cursor - documents matching the example [0...n]
1660      */
1661     public function range($collectionId, $attribute, $left, $right, array $options = [])
1662     {
1663         if ($attribute === '') {
1664             throw new ClientException('Invalid attribute specification');
1665         }
1666 
1667         if (strpos($attribute, '.') !== false) {
1668             // split attribute name
1669             $attribute = explode('.', $attribute);
1670         }
1671 
1672         $body = [
1673             self::OPTION_COLLECTION => $collectionId,
1674             self::OPTION_ATTRIBUTE  => $attribute,
1675             self::OPTION_LEFT       => $left,
1676             self::OPTION_RIGHT      => $right
1677         ];
1678 
1679         $body = $this->includeOptionsInBody(
1680             $options,
1681             $body,
1682             [
1683                 self::OPTION_CLOSED => null,
1684                 self::OPTION_LIMIT  => null,
1685                 self::OPTION_SKIP   => null,
1686             ]
1687         );
1688 
1689         $response = $this->getConnection()->put(Urls::URL_RANGE, $this->json_encode_wrapper($body));
1690 
1691         return new Cursor($this->getConnection(), $response->getJson(), $options);
1692     }
1693 
1694 
1695     /**
1696      * Get document(s) by specifying near
1697      *
1698      * This will throw if the list cannot be fetched from the server
1699      *
1700      *
1701      * @throws Exception
1702      *
1703      * @param mixed  $collectionId    - collection id as string or number
1704      * @param double $latitude        - The latitude of the coordinate.
1705      * @param double $longitude       - The longitude of the coordinate.
1706      * @param array  $options         - optional array of options.
1707      *                                <p>Options are :<br>
1708      *                                <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1709      *                                <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1710      *                                <p>
1711      *                                This is actually the same as setting hidden attributes using setHiddenAttributes() on a document. <br>
1712      *                                The difference is, that if you're returning a result set of documents, the getAll() is already called <br>
1713      *                                and the hidden attributes would not be applied to the attributes.<br>
1714      *                                </p>
1715      *
1716      *                                <li>'distance'  - If given, the attribute key used to store the distance. (optional)
1717      *                                <li>'batchSize' - can optionally be used to tell the server to limit the number of results to be transferred in one batch</li>
1718      *                                <li>'skip'      -  Optional, The number of documents to skip in the query.</li>
1719      *                                <li>'limit'     -  Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1720      *                                </li>
1721      *                                </p>
1722      *
1723      * @return Cursor - documents matching the example [0...n]
1724      */
1725     public function near($collectionId, $latitude, $longitude, array $options = [])
1726     {
1727         $body = [
1728             self::OPTION_COLLECTION => $collectionId,
1729             self::OPTION_LATITUDE   => $latitude,
1730             self::OPTION_LONGITUDE  => $longitude
1731         ];
1732 
1733         $body = $this->includeOptionsInBody(
1734             $options,
1735             $body,
1736             [
1737                 self::OPTION_DISTANCE => null,
1738                 self::OPTION_LIMIT    => null,
1739                 self::OPTION_SKIP     => null,
1740             ]
1741         );
1742 
1743         $response = $this->getConnection()->put(Urls::URL_NEAR, $this->json_encode_wrapper($body));
1744 
1745         return new Cursor($this->getConnection(), $response->getJson(), $options);
1746     }
1747 
1748 
1749     /**
1750      * Get document(s) by specifying within
1751      *
1752      * This will throw if the list cannot be fetched from the server
1753      *
1754      *
1755      * @throws Exception
1756      *
1757      * @param mixed  $collectionId    - collection id as string or number
1758      * @param double $latitude        - The latitude of the coordinate.
1759      * @param double $longitude       - The longitude of the coordinate.
1760      * @param int    $radius          - The maximal radius (in meters).
1761      * @param array  $options         - optional array of options.
1762      *                                <p>Options are :<br>
1763      *                                <li>'_sanitize'         - True to remove _id and _rev attributes from result documents. Defaults to false.</li>
1764      *                                <li>'_hiddenAttributes' - Set an array of hidden attributes for created documents.
1765      *                                <p>
1766      *                                This is actually the same as setting hidden attributes using setHiddenAttributes() on a document.<br>
1767      *                                The difference is, that if you're returning a result set of documents, the getAll() is already called <br>
1768      *                                and the hidden attributes would not be applied to the attributes.<br>
1769      *                                </p>
1770      *
1771      *                                <li>'distance'  - If given, the attribute key used to store the distance. (optional)
1772      *                                <li>'batchSize' - can optionally be used to tell the server to limit the number of results to be transferred in one batch</li>
1773      *                                <li>'skip'      -  Optional, The number of documents to skip in the query.</li>
1774      *                                <li>'limit'     -  Optional, The maximal amount of documents to return. 'skip' is applied before the limit restriction.</li>
1775      *                                </li>
1776      *                                </p>
1777      *
1778      * @return Cursor - documents matching the example [0...n]
1779      */
1780     public function within($collectionId, $latitude, $longitude, $radius, array $options = [])
1781     {
1782         $body = [
1783             self::OPTION_COLLECTION => $collectionId,
1784             self::OPTION_LATITUDE   => $latitude,
1785             self::OPTION_LONGITUDE  => $longitude,
1786             self::OPTION_RADIUS     => $radius
1787         ];
1788 
1789         $body = $this->includeOptionsInBody(
1790             $options,
1791             $body,
1792             [
1793                 self::OPTION_DISTANCE => null,
1794                 self::OPTION_LIMIT    => null,
1795                 self::OPTION_SKIP     => null,
1796             ]
1797         );
1798 
1799         $response = $this->getConnection()->put(Urls::URL_WITHIN, $this->json_encode_wrapper($body));
1800 
1801         return new Cursor($this->getConnection(), $response->getJson(), $options);
1802     }
1803 
1804     /**
1805      * @param $collection
1806      * @param $options
1807      */
1808     private function createCollectionIfOptions($collection, $options)
1809     {
1810         if (!array_key_exists(CollectionHandler::OPTION_CREATE_COLLECTION, $options)) {
1811             return;
1812         }
1813 
1814         $value = (bool) $options[CollectionHandler::OPTION_CREATE_COLLECTION];
1815 
1816         if (!$value) {
1817             return;
1818         }
1819 
1820         $collectionOptions = [];
1821         if (isset($options['createCollectionType'])) {
1822             if ($options['createCollectionType'] === 'edge' ||
1823                 $options['createCollectionType'] === 3
1824             ) {
1825                 // edge collection
1826                 $collectionOptions['type'] = 3;
1827             } else {
1828                 // document collection
1829                 $collectionOptions['type'] = 2;
1830             }
1831         }
1832 
1833         try {
1834             // attempt to create the collection
1835             $this->create($collection, $collectionOptions);
1836         } catch (Exception $e) {
1837             // collection may have existed already
1838         }
1839     }
1840 }
1841 
ArangoDB-PHP API Documentation API documentation generated by ApiGen