Firestore paginate documents for quiz app - firebase
I am building a quiz app and I am struggling about data structure in firebase.
Actually, I have two collections:
Questions collection, containing one document foreach question
Users Answers collection, containing one document foreach user. Inside user's document, there is one map per answered question where I store if question has been answered and if question has been right answered.
So, where is the problem ? For my app, I need two things:
Fetch list of a specific user answers. Actually there is no problem because I can query users answers collection for a specific user and retrieve all his answers within a single document.
Fetch list of a questions never answered by user. This is a quiz app, so it is mandatory to show questions never answered by user to progress in the game.
The current (not best) solution is this : when the user launch the app, I request all questions, get his answers and then I can know which question I should show to user and the ones I shouldn't. The problem of this solution is that I have to query all the questions documents so it represents a large number of reads (and firebase bill by number of reads 🙃).
I would like to paginate the number of questions to show to user (so questions never answered) to avoid extra-billing but I can't figure how to request them.
I tried to use not-in clause but it is limited to 10 items and I have a lot more than 10 questions.
I would like to know if you have any ideas to bypass this problem. Hope I'm clear enough.
Firestore doesn't support using the results of a query to exclude documents from another query. There are no SQL-like joins that query across documents in multiple collections.
If the provided inequality filter (10 items max) isn't sufficient for your use case, I'm afraid you're stuck with the solution you have now by filtering the results in the client app.
Some developers might choose to duplicate data into a SQL database to make these kinds of queries possible, but you'll have to decide for yourself if that's worthwhile.
We can consider this, I am wondering this could make your idea work.
This will only work when the users you know are constant.
Every questions docs need to have this property: not_answered_by
And set all users' ids list inside this property initially for all questions.
Once a user answered against one question then update certain question doc to remove that user id from not_answered_by So like this below, I remove user who has id:ccccc inside not_answered_by list from question :PXxzLaZp4kDSzewo7kht when user answered on that question.
Then you can run this query .where("not_answered_by", "array-contains", user_id) against questions collection to get all questions not answered by selected user.
If you have this structure of questions collection, then the powerful advantage is that you don't have to query double to get questions not answered by user, which does cost time and money. The remove action from not_answered_by doesn't affect speed low because you know which user id to be removed from which question id.
One tip: if you dont want to set not_answered_by to have all users' id list initially then just have another property: is_answer_started to set false for all questions. And whenever question is started to be answered then set not_answered_by to have all users' list.
not_answered_by is array of strings and it doesn't affect to your cost of firebase, important fact on your side is getting result in cheap and fast right?
Important to note: this is case of users' id list are constant, this doesn't work if users collection is dynamic which means user is added dynamically so please think this is a tricky method but I think it is best approach for now. PS: Firebase query doesn't support array_not_contains which I was about to find and use it. We can approach this in javascript via array includes function you know. :)
Vice versa, you can have answerd_by property inside question doc to get answered questions list against user.
Related
Database Design - creating multiple checklists of various sizes
My last question was closed due to being too vague, new more on point question here: Hey all I'm learning to develop using .NET Core and Angular, and am developing a WebApp to do this. I'm trying to figure out what the best would to build a database is for a specific portion of the project. This is a checklists module that will allow users to create checklists with customized questions that they would be able to pull up and answer as they complete each item. An example of what I'm looking to do is as follows: A user can create a checklist that has as many questions as they would like to create. The user can then pull that checklist up and provide the answers to each question. Answers will be either a string, boolean, checkbox options, image or various other types of input the user chooses when creating the checklist. Knowing that one user may create 3 questions, and another may create 50 questions, what is the best way to design the table for this to store each question? Would this be a table dedicated to just the name of the checklist, and then another with the list of questions and answers tied together via a join or one to many table? What is the best practice for this? Any input would be greatly appreciated!
Firebase Web - Getting UID's from other users
I'm trying to use the "orderByChild" functionality provided by Firebase, but I stumbled upon a roadblock. The structure of my database is very simple, it looks a bit like this: Root Users ${UID} ID Name Birthday ... Now, I'd like to search other user's names without knowing their UID. Does anyone have an idea on how to solve this problem? I could just download the users file completely but that does not seem like a good idea.
this about the question before posting it on stack overflow : you have to make a strategy to get this issue solved , I propose to you two possible solutions : 1)(very bad solution): you parse the data from firebase and you put them in [<String , anyObject>] and you loop over this array in order to get the username that you want to get. ** Ps: in term of performance and usability the worst thing that you could do is to invoke the database to get unuseful data, so don't use this solution in production. ** 2) you make a strategy for this: look over what should be the relationship between a user and another and add new field for example friends and store on it the uids that you want to get.
DynamoDB Update Item
Could someone please give some basic code on how to update items? I am using it an have an app that needs to add/delete values to list and map properties on table items without completely deleting the value. I also have a number property that I need to use as counter. In AWS documentation it simply states to re-save the entire object. I know it is possible to update items in this manner however I cannot seem to find any code. My app is in objective c however this seems like a problem for many people using many languages so this may be a great place to answer this for any and all languages. Thanks.
Counting Survey Answers of users ASP.Net
I'm building an online application for a survey. I want to count how many users answers a specific question. My question is, how would I count the answer using Session state and application state? The answers are inputs of radio boxes and check box lists.
Save the user replies in your database as normal, then come back later and query your database to answer questions like that.
Posting variable data
I am building an application in ASP.NET, C#, MVC3 and SQL Server 2008. A form is presented to a user to fill out (name, email, address, etc). I would like to allow the admin of the application to add extra, dynamic questions to this form. The amount of extra questions and the type of data returned will vary. For instance, the admin could add 0, 1 or more of the following types of questions: Have you a full, clean driving liscence? Rate your drivings skills from 1 to 5. Describe the last time you went on a long journey? etc ... Note, that the answers provided could be binary (Q.1), integer (Q.2) or free text (Q.3). How would I allow the posting of 0, 1 or more random values from the form back to my code? Any help would be greatly appriecated. Thanks in advance. PS. I asked a similar question regarding the storing of this data in sql, see here
You will need to use an EAV scheme for storage. For a discussion of the topic, along with common pitfalls and solutions, see Best Practices for Semantic Data Modeling for Performance and Scalability. Other alternatives are Sparse Columns and XML data type column, but I think EAV is superior most of the times.
You'll have to accomplish this using dynamic controls. Basically you'll read the question list from your database, inject zero or more custom controls to emit the question(s) and accept the answer(s). Probably wrapped in a repeater. On post back you'll have to rehydrate the dynamic controls so that you can get the values.
I have done this before when I worked on a survey tool. So first of all you need to decide what questions type you'll have. I had SingleOption, MultiOption and FreeText type questions. User logs into the admin screen and selects a type of question he wants to add. He then clicks on Add button, which submits a request to a controller/web service. Controller looks at type of question and adds a record into the database. Rough table structure below: QuestionID | SurveyId | QuestionTypeId 2 4 1 This is your basic structure. When you generate an interface for answering questions, you will retrieve all questions with a SurveyId = 4. You will then write an HTML helper that looks at question type and generates an appropriate control. When it comes to submitting a survey, or answers to your question, you will display all questions and answer fields in some div, say we call it "survey_questions". Inside this div will be a form which will contain all your questions and controls for answers (text inputs, checkboxes etc). You will then submit this form through jQuery to a controller/web service. Controller/Web Service will read survey id and it will iterate through all submitted values. You will then use these values to populate a table for storing survey results. I understand that this is very brief and abstract, but I have worked over a month on this, so if this is useful and you need further help, then please ask.
I found a great article that solves my problem. You can find it here