0

The structure of my Firestore follows.

Posts - Post # - Fields(Post Title, date, CommentId[])

Comments - Comment # - Fields(Title, date, UserId)

Users - User # - Fields(username, photo,...etc)

the user# is equivalent to UserId from the field in the comment.

meaning:

Posts - PostId7777 - Fields("Morning!", 02/04/22, [] {CommentId8888, ....))

Comments - CommentId8888 - Fields("Hello World!", 02/10/22, userid9999)

Users - userid9999 - Fields("exampleUser, ......)

Since I found this structure is the most efficient, whenever I load comments first I get the array of comment Ids from the post, then load the comments using collection.whereIn(FieldPath.documentId, commentIds).

and Then I load user info using the userIds from comment fields.

But the problem arises here.

Among the comments, there might be a duplicate author(user).

so let's say there are 5 comments. 3 comments have non-duplicate author, but the remaining 2 is from the same user.

so when I query mDB.collection("users").whereIn(FieldPath.docId(), uIDs).get() queryDocSnapshots will only have 4 snapshots because 2 comments are from the same author.

Please keep in mind that querying in a loop won't work since Firebase queries asynchronously. I need an alternative for the WHERE-IN.

public static void forum_get_comments_step_two(Context _context, String _action, ArrayList<Comment> _retVal, ArrayList<String> _uIds) {

        ArrayList<Comment> newRetVal = new ArrayList<>();

        mDb.collection("users").whereIn(FieldPath.documentId(), _uIds).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                int x = 0;
                for (DocumentSnapshot doc : queryDocumentSnapshots) {

                    Comment currVal = _retVal.get(x);

                    User user = new User(doc.getId(), doc.getString("username"),
                            Integer.parseInt(doc.get("emblem_league").toString()),
                            Integer.parseInt(doc.get("emblem_team").toString()));

                    newRetVal.add(new Comment(currVal.getPostId(), user, currVal.getDesc(),
                            currVal.getParentId(), currVal.getMentionId()));

                    x++;
                }
                sendBroadcast(_context, _action, true, newRetVal);
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.i(TAG, "getCommentsStep2 failure: " + e.getLocalizedMessage());
                sendBroadcast(_context, _action, false, null);
            }
        });
    }
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Sean LEE
  • 23
  • 4

1 Answers1

0

Please keep in mind that querying in a loop won't work since Firebase queries asynchronously.

It's true that Firebase API is asynchronous but you can create a separate Task object for each new Firestore call and use Tasks.whenAllSuccess() method, as explained in my answer from the following post:

One more thing to mention is that there is another helpful method present which is called Tasks.whenAllSuccess(Collection> tasks), so you can call this method with a list of Task objects. Please see another answer of mine that does that:

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