Reduce number of read in Firestore Android

后端 未结 1 479
隐瞒了意图╮
隐瞒了意图╮ 2020-12-15 14:01

I want to reduce number of reads in order to get Question\'s detail from QuestionCollection (Array of Questions) .

相关标签:
1条回答
  • 2020-12-15 14:03

    The most efficient schema I can think of, is the following:

    Firestore-root
        |
        --- questions (collections)
        |     |
        |     --- questionId (document)
        |            |
        |            --- questionId: "02cubnmO1wqyz6yKg571"
        |            |
        |            --- title: "Question Title"
        |            |
        |            --- date: August 27, 2018 at 6:16:58 PM UTC+3
        |            |
        |            --- comments (colletion)
        |            |     |
        |            |     --- commentId
        |            |            |
        |            |            ---commentId: "5aoCfqt2w8N8jtQ53R8f"
        |            |            |
        |            |            ---comment: "My Comment"
        |            |            |
        |            |            ---date: August 27, 2018 at 6:18:28 PM UTC+3
        |            |
        |            --- likes (colletion)
        |            |     |
        |            |     --- likeId (document)
        |            |            |
        |            |            --- userId: true
        |            |
        |            --- views (colletion)
        |            |     |
        |            |     --- viewId (document)
        |            |            |
        |            |            --- userId: true
        |            |
        |            --- tags ["tagId", "tagId"]
        |
        --- tags (collections)
              |
              --- tagId (document)
                    |
                    --- tagId: "yR8iLzdBdylFkSzg1k4K"
                    |
                    --- tagName: "Tag Name"
    

    In which the comments, likes and views are colletions under questionId document. Unlike in Firebase real-time database where to display a list of question you would have been downloaded the entire question object, in Cloud Firestore this is not an issue anymore. So to avoid querying using a where methods, you can simply get a specific question like this:

    FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
    DocumentReference questionIdRef = rootRef.collection("questions").document(questionId);
    questionIdRef.get().addOnCompleteListener(/* ... */);
    

    Because you can have hundreds, thousands or even more comments, likes and views to a single question, storing the data into an array will not help you. According to the official documentation:

    Cloud Firestore is optimized for storing large collections of small documents.

    For example, to get all the comments of a specific question, you can use the following query:

    Query query = rootRef.collection("questions/"+questionId+"comments").orderBy("date", Query.Direction.DESCENDING);
    

    Because a question can have only a few tags, you can simply use an array. To get all questions with a specific tag, you can use the following query:

    Query query = rootRef.collection("questions/"+questionId+"tags").whereArrayContains("tags", tagId);
    

    One more thing to remember, even if tags object is stored in the database as an array, document.get("tags") will return an ArrayList and not an array.

    If you also want to count the number of likes or any other number of documents within a collection, please see my answer from this post.

    Edit:

    According to your comments:

    If I want to show the most liked question of all to a user. How could I do this?

    You should add the number of likes as a property inside the question object and then you can query the database according to it like this:

    Query query = rootRef.collection("questions").orderBy("numberOfLikes", Query.Direction.DESCENDING);
    

    According to this you can also store the number of likes in the Firebase real-time database and you can increase/decrease it using Firebase Transactions.

    secondly if I want to show all the question related to a tag like mathematics (show all question which have mathematics tag) ??

    As also mentioned above you can take atvantage of the whereArrayContains method. You can also store the tags as String and not as id. For that, you need to change this structure:

    --- tags ["tagId", "tagId"]
    

    to

    --- tags ["mathematics", "chemistry"]
    

    And the code should look like this:

    Query query = rootRef.collection("questions/"+questionId+"tags").whereArrayContains("tags", "mathematics");
    

    the statement (userId: true) saves a lot of data repetition

    Yes it does.

    0 讨论(0)
提交回复
热议问题