arangodb / arangodb-php

PHP ODM for ArangoDB
https://www.arangodb.com
Apache License 2.0
183 stars 43 forks source link

remove document property by update does not work #196

Closed hwde closed 7 years ago

hwde commented 7 years ago

If I add a document to a collection, i.e.:

$user = new ArangoDocument();

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

$id = $handler->add('users', $user);

and later on want to remove the "age" property, the docs say:

$userFromServer = $handler->get('users', $id);
unset($userFromServer->age);
$result = $handler->update($userFromServer);

should do it, but "age:25" is still part of the document within the DB.

frankmayer commented 7 years ago

Could you please try again, using the 'keepNull' option? $result = $handler->update($userFromServer, ['keepNull'=>false]); This should remove the attributes that are not present (or have null as their value) in your patch document.

On the other hand you might also try replace instead of update, which will replace the complete document with the one given. The keepNull option does not apply in this case.

There are also other interesting options. You should check the documentation in the docs folder of the driver for more options and detailed description of the functionality.

Hope that helped.

hwde commented 7 years ago

Hi Frank,

thanks for quick response. First I thought I was wrong, because it was late at night ... but I here is what I get if I run these few lines of code of document.php from the example folder:

    // create another new document
    $user = new Document();
    $user->set("name", "j-lo");
    $user->level = 1;
    $user->vists = array(1, 2, 3);

    $id = $handler->save("users", $user);
    var_dump("CREATED A NEW DOCUMENT WITH ID: ", $id);

    // get this document from the server
    $userFromServer = $handler->getById("users", $id);
    var_dump($userFromServer);

    // update this document
    $userFromServer->nonsense = "hihi";
    unset($userFromServer->name);
    $result = $handler->update($userFromServer);
    var_dump($result);

    // get the updated document back
    $result = $handler->get("users", $id);
    var_dump($result);

This is what I get in console from the last var_dump(), please note that "name" is still "j-lo".

class triagens\ArangoDb\Document#9 (8) {
  protected $_id =>
  string(11) "users/95053"
  protected $_key =>
  string(5) "95053"
  protected $_rev =>
  string(5) "95057"
  protected $_values =>
  array(4) {
    'level' =>
    int(1)
    'name' =>
    string(4) "j-lo"
    'vists' =>
    array(3) {
      [0] =>
      int(1)
      [1] =>
      int(2)
      [2] =>
      int(3)
    }
    'nonsense' =>
    string(4) "hihi"
  }
  protected $_changed =>
  bool(true)
  protected $_isNew =>
  bool(false)
  protected $_doValidate =>
  bool(false)
  protected $_hidden =>
  array(0) {
  }
}

Hm, I replaced update() with replace(), still the same ... weird.

Environment: OSX or Debian 8.0, ArangoDB 3.0.7, arangodb-php (master or 3.0 branch).

hwde commented 7 years ago

Ah, now I understand ... unset(...) simply sets the value in document to NULL, so it will always remain in the document with NULL value, no matter if update() or replace() is used. So without setting ['keepNull'=>false] it is not possible to remove these properties.

frankmayer commented 7 years ago

Hi @hwde , while investigating this issue I stumbled upon some inconsistencies. I am planning to get a fix out today or tomorrow.

As for the suggested unset() method. It will not work on multidimensional arrays with the document object. For multidimensional data the only way to do this, is to use the update method with the 'keepNull'=> false option. However there is currently an issue that I am tracking, concerning this exact thing.

You should also note that the keepNull option has nothing to do with the unset() method.

The unset() method removes the attribute from the document object (or the array, i f you have used the getAll() method to retrieve the data part.) The data manipulation step after unset() is the replace() method. It will replace the complete stored document with whatever you give it.

The update() method on the other hand, in combination with the 'keepNull'=>false option, will remove those attributes inside the selected document, which have a null value.

I hope this helps.