3

Fairly new to Flutter and FireStore, I'm having trouble finding examples or explanations on how to add Maps to an Array (specifically, Creating the initial Array with a Map, then Reading then Adding more Maps to the collection of the Notes Array).

I have an Event Class for scheduling events and that is working very well. What I'm trying to add is a "Notes" field that would allow an some Administrator to add Notes on one day then come back and add to that Event another set of notes as things change. I don't want to "overwrite" the previous Notes, just keep adding more Notes to the Array of notes.

Specific questions:

  1. How do I Create the "Array" when adding the entry into FireStore using Flutter?
  2. How do I Read the data in the "Array" when it's coming back as a set of "Map fields" in Flutter?
  3. How do I just Add to the Array with a new Note? (I think this needs FieldValue.arrayUnion([someMap]) but I'm not certain as this appears to avoid any overwriting.

The page section here shows writing it out but little else: https://firebase.google.com/docs/firestore/manage-data/add-data#data_types

Below is an example of the FireStore structure I'm trying to create. enter image description here

Has anyone done this before and do you have some direction you can provide? The Firebase documentation in this space is thin...

1 Answer 1

4
  1. To create an new document with array in firestore:
FirebaseFirestore.instance.collection('path/to/collection').add(
  { 'notesArray': [
    {'date': 'sometime', 'notes': 'somenotes', 'user': 'someuser'}
  ]},
  SetOptions(merge: true),
);
// or
FirebaseFirestore.instance.collection('path/to/collection').add(
  { 'notesArray': []}, // for an empty array
  SetOptions(merge: true),
);
  1. To read the data:
FirebaseFirestore.instance.doc('company').get().then((value) {
  final doc = value.data()!;
  print(doc['lname']); // should print Gethsemane
  print(doc['notesArray'] as List); // should print notes array
  final notes = doc['notesArray'] as List;
  for (final note in notes) {
    print(note['date']);
    print(note['notes']);
    print(note['user']);
  }
  // or
  for (int i = 0; i < notes.length; i++) {
    print(notes[i]['date']);
  }
});
  1. Add new data to notes array. Simply use FieldValue.arrayUnion.

E.g

FirebaseFirestore.instance.doc('path/to/doc').set(
  {
    'notesArray': FieldValue.arrayUnion([
      {'date': 'sometime', 'notes': 'somenotes', 'user': 'someuser'}
    ]),
  },
  SetOptions(merge: true),
);
// I used set method along with setOptions in order not to 
// override other fields (e.g modifiedBy field)

Keep in mind that if your array is going to be very large, it is better to store the notes as a subcollection.

##EDIT##

If you want to update a nested array, you can use the dot notation.

class SchedulerEvents {
  final List<Map<String, dynamic>>? notes;
  SchedulerEvents({required this.notes});
}

// lets assume we have data like this that we want to update
final data = SchedulerEvents(
  notes: [
    {'date': 'sometime', 'notes': 'somenotes', 'user': 'someuser'},
  ],
);
FirebaseFirestore.instance.doc('path/to/doc').set(
  {
    'schedulerEvents.notes': FieldValue.arrayUnion([data.notes![0]]),
    // or
    'schedulerEvents.notes': FieldValue.arrayUnion(data.notes![0]),
    // 'schedulerEvents.lname: 'test', // to update other fields
  },
  SetOptions(merge: true),
);
// we used dot notation to update fields here.
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you @peter-obiechina, I'll give these a try and see if I can get the notesArray to work!
Thanks again Peter. The solution is VERY close right now but for the update, it appears that "FieldValue.arrayUnion" will ONLY take a string value for the field to update. In this case I have a custom object called "SchedulerEvents" with a field called "notes". Notes is a nullable List of type Map like so: "List<Map<String, dynamic>>? notes". When I try to invoke "FieldValue.arrayUnion" it complains that "The argument type 'FieldValue' can't be assigned to the parameter type 'List<Map<String, dynamic>>?'" - have you run into something like this before?
I think so, but let me be sure I understand you. You want to add an Array to a field named 'notes' in an object named 'SchedulerEvents'? You can use the dot notation. I will update my answer (check the bottom part labelled edit). And FieldValue.arrayUnion can accept Map and List<Map> as shown in the Edit answer.
Thanks Peter! I've started a specific thread on this specific issue at the link below. The issue seems to be that the FieldValue.arrayUnion function will ONLY accept a string value for the field to point to. My testing seems to show that a pre-defined field doesn't work well? I've also included the entire code for 'SchedulerEvents': stackoverflow.com/questions/73651218/…
Great work Peter! Thanks Again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.