Why successListener is called even if element is not inserted into an array in Firestore document?

Viewed 99

I use the following code to add userId to an array in a Cloud Firestore document:

DocumentReference reference = firebaseFirestore.collection("photos").document(photoId);
reference.update("views", FieldValue.arrayUnion(currentUser.getUid()))
        .addOnSuccessListener(new OnSuccessListener<Void>()
        {
            @Override
            public void onSuccess(Void aVoid)
            {
                reference.update("viewsCount", FieldValue.increment(1));
            }
        });

As you can see from the code, I want the viewsCount to increment only if element is added to the views array.

According to this Adding Data document, arrayUnion() adds elements to an array but only elements not already present, and thats exactly what I wanted.

But, the problem is that when I add an already present element into the array, the element is not inserted, but addOnSuccessListener is called, viewsCount is incremented and failureListener is never called. Is there any way to prevent this? I want the viewsCountto be incremented only when an element is inserted into views array.

1 Answers

But, the problem is that when I add an already present element into the array, the element is not inserted, but addOnSuccessListener is called, viewsCount is incremented and failureListener is never called.

That's the normal behaviour. Please note that the OnSuccessListener that you are currently using is called for an operation that you have performed in the database only if the final result of that particular operation succeeded.

In your particular case:

.update("views", FieldValue.arrayUnion(currentUser.getUid())

The OnSuccessListener is called after the operation that is adding the uid to your views array succeeded. It doesn't really matter if that uid was already there or not, the entire operation succeeded. It's true that the uid was not added to the array but even though, the operation was successful.

Please also rememeber, that a Task is considered successful when the work represented by the Task is finished, as expected, with no errors. On the other hand, OnFailureListener is called when a Task fails with an exception. So it can be a result or an Exception, never both. So adding an uid that already exsists in an array can never be cosidered a failure.

To solve this, you should create a get() call, get the entire document and check the existnce of the uid in views array. If it doesn't exist, create the update and increment the counter, otherwise take no action.

Related