3

I'm using php sdk to delete some fields from firestore database, i want to delete a map from an array inside a document, but instead the function used delete all maps inside the parent array.

My firestore database looks like this firebase database

What i'm trying to do is remove a specific index ex: index 0 with it's children from imageUrls array not all the maps inside it.

I tried these 2 functions :

$usersRef->update([
        ['path' => 'imageUrls.image_url', 'value' => FieldValue::arrayRemove(['image.png'])]
    ]);

and this one

$usersRef->update([
    ['path' => 'imageUrls.image_url', 'value' => FieldValue::deleteField()]
]);

The first function remove all imageUrls childrens and change imageUrls type from array to map, while the second one nothing happened. All the fields still exist in the document and no deletion occurd

<?php 

namespace App\Services;
use Google\Cloud\Firestore\FirestoreClient;
use Google\Cloud\Firestore\FieldValue;
use Google\Cloud\Firestore\FieldPath;

class FirebaseService
{
    public function delete()
    {
        // Create the Cloud Firestore client
        $db = new FirestoreClient(
            ['projectId' => 'MyProjectId']
        );

        $usersRef = $db->collection('NewStories')->document('1');

        $usersRef->update(
                         [
                              ['path' =>'imageUrls.image_url', 
                              'value' => FieldValue::arrayRemove(['image.png'])]
                         ]);  
    }
}
Deniss T.
  • 2,526
  • 9
  • 21
Aref Makke
  • 49
  • 10

1 Answers1

1

This can be achieved using the arrayRemove() method. As the PHP Client for Firestore says

Returns a special value that can be used with set(), create() or update() that tells the server to remove the given elements from any array value that already exists on the server. All instances of each element specified will be removed from the array. If the field being modified is not already an array it will be overwritten with an empty array.


Update:

Firebase does not support updating an existing element in an indexed array. More information can be found in the Official Documentation.

Workaround:

Reading the entire array out of the document, make modifications to it in memory, then update the modified array field entirely.**

Credits to this Firestore Update single item in an array field case.

sllopis
  • 2,292
  • 1
  • 8
  • 13
  • As i mention in description that arrayRemove is deleteing all image_url inside imageUrls even i'm giving it the exact name. also as per docummentation `// falsey is good enough unless the field is actually 0. if (!$field && $field !== 0)` so i can't access element at index 0 – Aref Makke Oct 08 '19 at 13:42
  • 1
    Please check out this similar [OS case](https://stackoverflow.com/questions/52187985/firestore-update-single-item-in-an-array-field) – sllopis Oct 09 '19 at 12:39
  • It didn't help, they didn't give him a solution instead they ask to update document but remain the index zero is the problem – Aref Makke Oct 11 '19 at 09:22
  • 1
    I will try to explain conceptually what could work for you. You will need to get the reference of document "1", which you already have. Then, you will need to access de array imgeUrls. After, you will have go to one level deeper and access the nested array "0" or "1", as I can see in the image, to be able to update and erase the field "image_url" with the value "image.png". This may give you an idea code wise [here](https://stackoverflow.com/questions/55875241/how-to-remove-an-array-item-from-a-nested-document-in-firebase) – sllopis Oct 11 '19 at 10:54
  • I don't know how firebase handle the arrayRemove i'm using this `$usersRef = $db->collection('NewStories')->document(1); $usersRef->update([ ['path' => 'imageUrls.1', 'value' => FieldValue::arrayRemove(['svg.jpg'])] ]);` and it's actually removing children index (1) ignoring if value exist or not. Weird isn't – Aref Makke Oct 14 '19 at 07:38
  • If you read the [documentation](https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array), `.arrayRemove()` removes all instances of each given element. I believe that removing the children is expected. Maybe what you need is [delete a field](https://firebase.google.com/docs/firestore/manage-data/delete-data#fields). Let me know if it works. – sllopis Oct 14 '19 at 08:04
  • So actually it doesn't matter if you add a true or false value inside array as it will remove all. `FieldValue::deleteField()` didn't work also. What i did is i read the entire array out of the document, make modifications to it, then update the modified array field entirely. I couldn't find a solution since `Google\Cloud\Firestore\FieldValue` doesn't read index 0 as mentioned in my comment above that seems the best way to do it. – Aref Makke Oct 14 '19 at 10:09
  • I updated my answer some days ago with a workaround, which worked for other community users. Were you able to modify this field value using the workaround version? – sllopis Oct 14 '19 at 10:46
  • I used the solution from [OS case](https://stackoverflow.com/questions/52187985/firestore-update-single-item-in-an-array-field) you mentioned above after a long search i didn;t find any better solution so i use it as you described in your workaround version – Aref Makke Oct 15 '19 at 06:40
  • If this workaround fixed your issue, could you please mark this answer as accepted for greater visibility to other community users? Thanks. – sllopis Oct 15 '19 at 08:01