Kaiser
Kaiser

Reputation: 606

How to create new documents all at the same time in Firestore?

In am creating a quiz app and when a player clicks on a certain button, it creates the new game in the database and opens the next activity (game activity). I am not sure which approach is the best way to set up new documents in the database.

Basically what I want to know is, which of the following approaches is the best way and am I am right with the assumptions. The goal is to find the best way to assure that the user only gets to the next activity when all documents got created.

  1. Approach:

I assume that this is faster than the second approach but has the risk that some documents/ sub-collections will not be created. (I have a lot more documents that are created but fir simplicity I just show some)

...

gameRef.document(gameId).collection("Uid").document("Uid").set(uidPlayers);
gameRef.document(gameId).collection("Turn").document("Turn").set(mTurn);
gameRef.document(gameId).collection("Game Status").document("Game Status").set(gameStatus);
gameRef.document(gameId).collection("Timestamp").document("Timestamp").set(timeStamp);

Intent i = new Intent(FriendDetailActivity.this, GameActivity.class);
startActivity(i);

...
  1. Approach:

This approach is safer than the first since it assures that every document /sub-collection will be created before the user exits this activity but it does take longer. Also I simplified the code here. It is safer, because after every creation I add an onCompleteListener.


...

gameRef.document(gameId).collection("Round").document("Round").set(round)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {

                db.collection("User").document(uidPlayer1).collection("Games").document(uidPlayer2).set(gameUser)
                        .addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {

                                db.collection("User").document(uidPlayer2).collection("Games").document(uidPlayer1).set(gameUser2)
                                        .addOnCompleteListener(new OnCompleteListener<Void>() {
                                            @Override
                                            public void onComplete(@NonNull Task<Void> task) {

                                                Intent i = new Intent(FriendDetailActivity.this, GameActivity.class);
                                                startActivity(i);
                                            }
                                        });
                            }
                        });
            }
        });

...

Upvotes: 1

Views: 190

Answers (2)

McKay M
McKay M

Reputation: 448

Doug's answer looks great.

If you don't want to batch write, you can also try using CompleteableFuture.allOf instead of those nested callbacks.

Here's the API docs for it.

Upvotes: 1

Doug Stevenson
Doug Stevenson

Reputation: 317372

If you want to make sure all documents are written at the same time, use a batch write to create them all at the same time. There will be no need to check individual status. The batch will either happen all at the same time, or fail all at the same time.

WriteBatch batch = db.batch();

DocumentReference uidRef = gameRef.document(gameId).collection("Uid").document("Uid");
batch.set(uidRef, uidPlayers);

// add more documents...

batch.commit().addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        // ...
    }
});

Upvotes: 3

Related Questions