David
David

Reputation: 839

How can I filter documents in Firestore based on an array stored in another collection?

I have a Firestore database organized like so:

FirestoreDB FireStore DB

I have three fragments which display: all posts, posts of individuals that user is following and all the posts by the user. My issue is with getting the posts of individuals that user is following to work, the other two work.

I previously have tried to get the array from Firestore and use that array to query the posts of followed users but I am unable to access the array outside of the method that generates it as described here: https://firebase.google.com/docs/firestore/query-data/get-data#get_a_document

Like so:

DocumentReference docRef = db.collection("following").document(currentUser.getUid());
        docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document.exists()) {
                        List<String> group = (List<String>) document.get("following");
                    } else {
                    }
                } else {
                }
            }
        });

Query posts = db.collection("posts").whereEqualTo("userId", group);//Does not compile since cannot resolve group.

Where I then created an array using the DocumentSnapshot however since my query is outside the scope of the method I cannot use the created array.

What I currently have that does not work is the following:

Query posts = db.collection("posts").whereEqualTo("userId", FirebaseFirestore.getInstance()
                .collection("following")
                .document(currentUser.getUid()));

Thank you for any help you can provide.

final Issue

private void readData(MyCallback callback){
        DocumentReference docRef = db.collection("following").document(currentUser.getUid());
        docRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    for (DocumentSnapshot document : Objects.requireNonNull(task.getResult())){
                        String group = document.getString("following");
                        followingList.add(group);
                    }
                    callback.onCallback(followingList);//says must be declared final
                } else {
                }
            }
        });
    }

Upvotes: 1

Views: 1779

Answers (1)

Alex Mamo
Alex Mamo

Reputation: 138989

There two main issues in your code. The first one would be at the following line of code:

Query posts = db.collection("posts").whereEqualTo("userId", group);

The group object is not in the scope where it is defined, so that's why you have a compilation error. Beside that, there is no way you can pass to the whereEqualTo() method, as the second argument a list. If you want to create a new query for each user in your array, you should iterate over it and pass as the second argument a String.

Second issue is that onComplete() has an asynchronous behaviour. Even if you have created the list as a global variable, it won't work since that method returns immediately and the value of your group list you're trying to use it outside the onDataChange() method, will not have been populated from the callback yet.

A quick solve for this problem would be to move the above line of code inside the onComplete() method and pass a String and not a list, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Upvotes: 2

Related Questions