How can I update a document array field using cloud_firestore ?

Hi everyone,

I am developing my first FF app. I am currently trying to figure out how to update a document array field using cloud_firestore package.

You can find below the custom code I have written to write/update some array field on documents from my "songs" Firestore collection. The code compiles without errors but the "update" part of it has absolutely no effect when the action is triggered (as opposed to the "write" part, which produces the expected result).

Can you please help me understand what is going on ?

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'package:cloud_firestore/cloud_firestore.dart';

Future<String> createOrUpdateSong(
    String songName,
    String albumName,
    String artistName,
    String moodLabel,
    String songUrl,
    String imageUrl) async {
  // Access the Firestore collection "songs"
  final songsCollection = FirebaseFirestore.instance.collection('songs');

  // Check if a document with the given song name (+ album/artist names) exists
  final existingSongSnapshot = await songsCollection
      .where("name", isEqualTo: songName)
      .where("album_title", isEqualTo: albumName)
      .where("artist_name", isEqualTo: artistName)
      .get();

  if (existingSongSnapshot.docs.isNotEmpty) {
    // If the song document exists, access its "moods" subcollection
    final songId = existingSongSnapshot.docs[0].id;
    final songReference = await songsCollection.doc(songId).get();
    final currentSongNumPosts = songReference.get('num_posts') as int;
    await songsCollection
        .doc(songId)
        .update({'num_posts': currentSongNumPosts + 1});

    // Check if a mood document with the given mood label exists in the "moods" subcollection
    final moodsSubcollection =
        await songsCollection.doc(songId).collection('moods');
    final existingMoodSnapshot =
        await moodsSubcollection.where("label", isEqualTo: moodLabel).get();

    if (existingMoodSnapshot.docs.isNotEmpty) {
      // If the mood document exists, update its "num_posts" field by adding 1
      final moodId = existingMoodSnapshot.docs[0].id;
      final moodReference = await moodsSubcollection.doc(moodId).get();
      final currentNumPosts = moodReference.get('num_posts') as int;
      await moodsSubcollection
          .doc(moodId)
          .update({'num_posts': currentNumPosts + 1});
    } else {
      // If the mood document doesn't exist, create a new one with "num_posts" set to 1
      await songsCollection.doc(songId).update({
        'moods': FieldValue.arrayUnion([
          {'label': moodLabel, 'num_posts': 1}
        ])
      });
    }
    return songId;
  } else {
    // If the song document doesn't exist, create a new song document with a mood subcollection document
    final newSong = {
      'name': songName,
      'album_title': albumName,
      'artist_name': artistName,
      'moods': [
        {'label': moodLabel, 'num_posts': 1}
      ],
      'num_posts': 1,
      'song_url': songUrl,
      'image_url': imageUrl
    };
    final songId =
        await songsCollection.add(newSong).then((DocumentReference doc) {
      return doc.id;
    });
    return songId;
  }
}

// Set your action name, define your arguments and return parameter,
// and then add the boilerplate code using the button on the right!

2
2 replies