0

players array in firestore

struct Game: Codable {
    
    let id: String
    
    var table = Table()
    
    var players = [Player]()
    
    var player1ID = ""
    var player2ID = ""
    
    var currentPlayerSetCountShouldAnimate = false
    var opponentSetCountShouldAnimate = false
    
    init(currentPlayer: Player) {
        id = UUID().uuidString
        players.append(currentPlayer)
        players[0].playerNumber = 0
        player1ID = currentPlayer.id
    }
}

struct Player: Codable, Equatable {
    var id = UUID().uuidString
    
    var playerNumber = 0
    
    var selectedCards: [Card]
    var collectedSets: [Card]
    var selectedCardsIndexes: [Int]
    
}

I'm storing the Game object in a Firestore database. Rather than updating the entire game when a Card object is added to the selectedCards array, I want to update only the selectedCards array for the currentPlayer.

func updatePlayerSelectedCards(player: Player) {
    do {
        let selectedCards = try JSONEncoder().encode(player.selectedCards)
        let gameRef = Firestore.firestore().collection("Game").document(game.id)
        let playerRef = gameRef.collection("players")

        playerRef.document("\(player.playerNumber)").updateData(["selectedCards": selectedCards]) { (error) in
            if let error = error {
                print("Error updating selectedCards field: \(error)")
            } else {
                print("Successfully updated selectedCards field")
            }
        }
    } catch {
        print(error.localizedDescription)
    }
}

I've written a number of variations on this function, but when I try to access the playerNumber index of the players array, it gives me this error:

[FirebaseFirestore][I-FST000001] WriteStream (7f9b27810c08) Stream error: 'Not found: No document to update: projects/setgamebc/databases/(default)/documents/Game/FC600D8C-85DC-4465-8648-31FFA90086EB/players/0'

In the attached image, it's clear that the index (0 in this case) exists in the player array. Is it not a document? Do I need to use FieldValue.arrayUnion for this? This is my first "large" project, and I feel like accomplishing this shouldn't be that hard, so I think I may be missing something simple. Any help and clarification would be greatly appreciated.

1
  • There is no operator to update an item in an array field in Firestore; the only operators are to add a unique item, remove specific items, or to set the entire field. So you'll have to: 1) read the array, 2) update it in your application code, 3) write the entire array back to the database. Commented Jan 3, 2023 at 20:25

1 Answer 1

0

The problem starts here:

let playerRef = gameRef.collection("players")
playerRef.document("\(player.playerNumber)")...

This code tries to update a $player.playerNumber document in a players collection. But your screenshot shows a players field in an otherwise named document. So there is no document called players, which explains the error message.

There is no way operator to update an item in an array field in Firestore; the only operators are to add a unique item, remove specific items, or to set the entire field.

So if the array_union operator is not good enough for your use-case, you'll have to: 1) read the array, 2) update it in your application code, 3) write the entire array back to the database.

Also see: Firestore Update single item in array of objects

Sign up to request clarification or add additional context in comments.

Comments

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.