Delete map in a firestore table

Viewed 358

I am having trouble deleting Maps in a data table in Firestore. Indeed, either I delete my entire array, or I receive an error of the type:

flutter: Failed to delete 1: Invalid argument: Instance of '_CompactLinkedHashSet '

I am attaching my classes to you so that you can understand better.Thank you in advance

CLASS Delete_description :

import 'package:cloud_firestore/cloud_firestore.dart';

class DeleteDescription {
  final String city;
  final String citee;
  final int value;
  CollectionReference cities = FirebaseFirestore.instance.collection('city');

  DeleteDescription(this.city, this.citee, this.value) {
    deleteDescription();
  }

  Future<void> deleteDescription() {
    return cities
        .doc(city)
        .collection("citee")
        .doc(citee)
        .set({
          "Description": FieldValue.arrayRemove([
            {0}
          ])
        })
        .then((value) => print("$citee Deleted"))
        .catchError((error) => print("Failed to delete $value: $error"));
  }
}

CLASS READDESCRIPTION:

import 'package:ampc_93/fonction/firebase_crud/delete_description.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class ReadDescription extends StatefulWidget {
  final String titreCity;
  final String titreCitee;

  ReadDescription(this.titreCity, this.titreCitee);

  @override
  _ReadDescriptionState createState() => _ReadDescriptionState();
}

class _ReadDescriptionState extends State<ReadDescription> {
  @override
  Widget build(BuildContext context) {
    CollectionReference cities = FirebaseFirestore.instance.collection("city");
    return FutureBuilder<DocumentSnapshot>(
      future: cities
          .doc(widget.titreCity)
          .collection("citee")
          .doc(widget.titreCitee)
          .get(),
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return Text("Something went wrong");
        }
        if (snapshot.hasData && !snapshot.data!.exists) {
          return Text("Documents does not exist");
        }
        if (snapshot.connectionState == ConnectionState.done) {
          var data = snapshot.data!.data() as Map<String, dynamic>;
          if (data["Description"] == null) {
            return Text("");
          } else {
            return ListView.separated(
                itemBuilder: (context, index) {
                  return ListTile(
                      title: Text(
                        data["Description"][index]["Identite"],
                        textAlign: TextAlign.justify,
                      ),
                      subtitle: Text(
                        data["Description"][index]["Role"],
                        textAlign: TextAlign.justify,
                        style: TextStyle(
                            decoration: TextDecoration.underline,
                            color: Colors.red),
                      ),
                      leading: Icon(Icons.person),
                      trailing: IconButton(
                        onPressed: () => DeleteDescription(
                            widget.titreCity, widget.titreCitee, index),
                        icon: Icon(Icons.delete_forever),
                        color: Colors.red[300],
                      ));
                },
                separatorBuilder: (context, index) => Divider(),
                itemCount: data["Description"].length);
          }
        }
        return Text("Loading");
      },
    );
  }
}

I specify that in my database, "Description" is an array and that I would therefore like to delete all the elements of "Description" number 0 for example

FIRESTORE DATABASE

2 Answers

The FieldValue.arrayRemove you are using didn't work in this way. There are two methods to delete data from firestore list. First way is pass element (Not it's index) in FieldValue.arrayRemove which you wants to delete. Second way is get collection from firestore and modify data according to your need and update collection in firestore. Have a look on below code for more understanding.

import 'package:cloud_firestore/cloud_firestore.dart';

class DeleteDescription {
  final String city;
  final String citee;
  final int value;
  CollectionReference cities = FirebaseFirestore.instance.collection('city');

  DeleteDescription(this.city, this.citee, this.value) {
    deleteDescription();
  }

  Future<void> deleteDescription() {
   final snapshot = await cities.doc(city).collection("citee").doc(citee).get();
  
  /* Get list from firestore */
  final list = snapshot["Description"] as List;
 
  /* Remove first or any element and delete from list */
  list.removeAt(0);
  
  /* Update same list in firestore*/
  await cities
    .doc(city)
    .collection("citee")
    .doc(citee)
      .set({"Description": list}).then((value) => print(" Deleted"));

   
  }
}

A helpful way to consider Firestore "Arrays" is that they are ABSOLUTELY NOT ARRAYS - they are ORDERED LISTS (ordered either by the order they were added to the array, or the order they were in in an array passed to the API as an array), and the "number" shown is the order, not an index. The only way to "identify" a single element in a Firestore Array[ordered list] is by it's exact and complete value. It is VERY unfortunate they chose the name "array".

That said, when you read a document, the result presented to your CODE is in the form of an array, and GAINS the ability to refer to an element by index - which is why you have to EITHER:

=> at the backend / API call, specify an element by "value", which in this case is the ENTIRE object on the list

OR

=> at the Client, read the document, delete the desired element either by index or value, then write the entire array back to the backend.

Related