1

I have an Android Studio project with 2 user collections: trainers and trainees. I want to make a method that receives the user's string email as input (the user's email is the document ID in both collections and a user can be either in the trainees collection or in the trainers collection not in both) and the method returns a boolean containing true if the user is a trainer and false if he isn't (meaning he is a trainee).

This is the code I came up with but its not working, it returns false all the time even if the user is a trainer. Am I doing something wrong? is there a better way to do this?

public static boolean isTrainer(String email)
{
    FirebaseFirestore firestore = FirebaseFirestore.getInstance();
    DocumentReference trainerRef = firestore.collection("trainers").document(email);
    DocumentReference traineeRef = firestore.collection("trainees").document(email);
    // Check if the trainer document exists
    Task<DocumentSnapshot> trainerTask = trainerRef.get();
    boolean isTrainer = trainerTask.isSuccessful() && trainerTask.getResult().exists();
    // Check if the trainee document exists
    Task<DocumentSnapshot> traineeTask = traineeRef.get();
    boolean isTrainee = traineeTask.isSuccessful() && traineeTask.getResult().exists();
    // If the trainer document exists but the trainee document doesn't, the user is a trainer
    Log.d("FirestoreExample", "isTrainer: " + isTrainer + ", isTrainee: " + isTrainee);
    return isTrainer && !isTrainee;
}

I tried many things but nothing worked

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Raz Dar
  • 13
  • 3
  • Aside from my answer, I think that you might also be interested in reading this [resource](https://medium.com/firebase-tips-tricks/how-to-read-data-from-cloud-firestore-using-get-bf03b6ee4953). – Alex Mamo Mar 27 '23 at 06:30

1 Answers1

0

If you don't know ahead of time if a user is a trainer or a trainee, then you have to explicitly check that. As I see in your code, you have two different collections, trainers and trainees. Which in your case, doesn't help much, because you have to perform two different checks.

So in your case, I would recommend a schema with a single collection that looks like this:

db
|
--- users (collection)
     |
     --- $email (document)
           |
           --- type: "trainee"
           |
           --- //other user fields

To check if a user is a trainer or a trainee, you only have to create a reference that points to the user document, read the document, and check the type of the user like this:

FirebaseFirestore db = FirebaseFirestore.getInstance();
CollectionReference usersRef = db.collection("users");
DocumentReference emailRef = usersRef.document(email);
emailRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {
        if (task.isSuccessful()) {
            DocumentSnapshot document = task.getResult();
            if (document.exists()) {
                String type = document.getString("type");
                if(type.equals("trainer")) {
                    //Do something.
                } else {
                    //Do something else.
                }
            }
        } else {
            Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
        }
    }
});

When you call DocumentReference#get(), the type of object that is returned is a Task<DocumentSnapshot>. So in order to get the result, you have to attach a listener, which is an asynchronous operation There is no way you can make that operation synchronous. This means that you cannot return the result of an asynchronous operation as a result of the method. For more information, I recommend you read my answer in the following post:

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193