How to expire a data after some specific time in firebase? - firebase

I am creating a School exam application where I give some questions to the database(firestore) and I want to expire those data from the database after some specific time!! how to do this in firebase

Client-side centric:
Record a "timestamp" upon creation of the exam.
Make the client show the exam as "expired" if and when ("now" >= "timestamp + # of days or hours")
OR:
Server-side...
If you actually want to delete the data from the db or mark it as "expired", you can create a Firebase function.
Let's assume that when creating an exam/question, you're adding an "expiration_time" when that data is supposed to be marked as "expired" or be deleted altogether.
Have your Firebase function do the following:
Query data where the "expiration_time" is less than or equal to "now".
For each result, mark that data as "expired" or delete it altogether, depending on your use case.
After you test your function and you know it works, make it so that it's a "Scheduled Firebase function" (google it if you don't know, it's easy to set up) - for example, make it run every minute.

Related

Firebase cloud function timestamp

In my current application, I store a value in Firestore for each user something along the lines of this:
User1Doc - hasUsedFeatureToday = true
User2Doc - hasUsedFeatureToday = false
...
At the end of the day, I run a scheduled function that resets all of these to false. This was fine while my application was relatively small, but does not scale very effectively as I'm sure you can imagine.
Each user can only use this aspect of my app once per day, so the only time this field is read is when they try to use it.
I would like to change this system to store a timestamp in the user's document when they use the feature and then check if this timestamp is the same day (Europe/London time) if someone tries to use it again.
Does Firebase offer a way to get a "timezoned" timestamp like this and store/check it with the Firestore?
You can just store a timestamp (UTC). Whenever users logs in to your app, just check the timestamp and update the same. You can always use libraries like Luxon to get local time from the UTC time.
If you want to allow the user to update this timestamp only once, you can use security rules to restrict the same. However, user may try to prevent the timestamp from being updated at first place.
You can instead use Cloud Function to serve the data only when the user requests it. This will be better than updating documents of all users even if they won't be using the feature every day.

Prevent inserting data to Firebase after cutoff date in Flutter app

In my flutter application I want to prevent users to enter their nominations after the cutoff date.
For example, there is an exam nomination with cutoff date 31st March 2020. I am inserting the nomination data from my flutter app to the Firebase database. In app I'm checking the current date should be before the 31st March and then only allow to enter the data. However if the user changes the mobile data to backward the the app will allow to enter the nominations for the exam.
I know if I write the Firebase Cloud Function and move my insert code there it will solve the issue. But I have lot of code that I will have to rewrite :-(. Is there any other solution that will allow me to know the actual current date? What if the internet is off?
Thanking you in advance
You could maybe write a small amount of backend code to read the Firebase server timestamp and use that to check the cutoff. See this code:
exports.currentTime = functions.https.onRequest((req, res) => {
res.send({"timestamp":new Date().getTime()})
})
I got this from this SO answer so don't ask me for more details :-)
How to save the current date/time when I add new value to Firebase Realtime Database
Not sure about how to handle the Internet off... but if you can't read the server date, they can't submit the results.
Your only option that doesn't involve writing backend code is to use security rules to restrict database writes based on the current date. What you will have to do is set up a rule on the collection that should be restricted, and it will have a line that looks something like this:
allow write: if request.time < timestamp.date(yyyy, mm, dd);
Where yyyy, mm, and dd are the components of the date. If you want something more specific, read the security rules API docs for timestamp functions - you will have to provide an time in epoch milliseconds. Note that timestamps in security rules are always measured in UTC.

Get auto-Id by time

In my app I use Firebase's childByAutoId() (swift) or .push() (web) to insert some data in the following format:
- events
- $autoId
- time:
- name:
- $autoId
- time:
- name:
Where $autoId are the randomly generated keys Firebase makes. time is the epoch time of when the data was pushed.
I want to allow users to modify each inserted entry's time. However, I want to keep the nodes under events sorted by their key and by time which Firebase naturally does when you use .push(). But if they modify the time so that it should actually be in a different order, the entries won't be sorted correctly.
Is there a way to generate an id by the modified time so that if it were inserted into events it would be in the right order? That way I could just delete the old entry and insert the new one while just duplicating the data.
Since the algorithm for Firebase's push IDs is well documented, you could easily modify the function to generate them based on a specific timestamp.
But I'd recommend instead keeping the necessary values as named properties for each child node. If you need to be able to sort by both creation and modification time, keep two separate properties. That way you won't have to depend on the behavior of the push IDs, but instead use more explicitly named properties to accomplish what you need.

Firebase - Structuring Data For Efficient Indexing

I've read almost everywhere about structuring one's Firebase Database for efficient querying, but I am still a little confused between two alternatives that I have.
For example, let's say I want to get all of a user's "maxBenchPressSessions" from the past 7 days or so.
I'm stuck between picking between these two structures:
In the first array, I use the user's id as an attribute to index on whether true or false. In the second, I use userId as the attribute NAME whose value would be the user's id.
Is one faster than the other, or would they be indexed a relatively same manner? I kind of new to database design, so I want to make sure that I'm following correct practices.
PROGRESS
I have come up with a solution that will both flatten my database AND allow me to add a ListenerForSingleValueEvent using orderBy ONLY once, but only when I want to check if a user has a session saved for a specific day.
I can have each maxBenchPressSession object have a key in the format of userId_dateString. However, if I want to get all the user's sessions from the last 7 days, I don't know how to do it in one query.
Any ideas?
I recommend to watch the video. It is told about the structuring of the data very well.
References to the playlist on the firebase 3
Firebase 3.0: Data Modelling
Firebase 3.0: Node Client
As I understand the principle firebase to use it effectively. Should be as small as possible to query the data and it does not matter how many requests.
But you will approach such a request. We'll have to add another field to the database "negativeDate".
This field allows you to get the last seven entries. Here's a video -
https://www.youtube.com/watch?v=nMR_JPfL4qg&feature=youtu.be&t=4m36s
.limitToLast(7) - 7 entries
.orderByChild('negativeDate') - sort by date
Example of a request:
const ref = firebase.database().ref('maxBenchPressSession');
ref.orderByChild('negativeDate').limitToLast(7).on('value', function(snap){ })
Then add the user, and it puts all of its sessions.
const ref = firebase.database().ref('maxBenchPressSession/' + userId);
ref.orderByChild('negativeDate').limitToLast(7).on('value', function(snap){ })

Efficiently storing and retrieving likes

In my Firebase database I have posts and then authenticated users can "like" posts. How can I efficiently get the number of likes a post has received. I know using MongoDB I can add/remove the user's id to a list and then use a MongoDB function to get the length of it very quickly and set that equal to the likes amount, but I'm not suer how to do that using Firebase. I could also add/remove it to the list and increment a likeCount variable, but that seems like it would cause concurrency issues unless Firebase has a function for that. What functions can I call to best handle this and scale well? Thanks in advance!
You can do both things:
1) Create a votes node with the UID as key and a value to sum up all the votes.
post:{
//All the data
likes:{
$user_1:1,
$user_2:-1,
}
}
And then just get a SingleValue Event or a Value event(depending if you want to keep track of changes) and sum up all the children
2)You can use a transaction block and just save a value and increase or decrease it depending on the votes
(here is a link where you can find transactions for android,iOS or java)
https://firebase.google.com/docs/database/web/save-data#save_data_as_transactions
post:{
//All the data,
likes:2,
}
It really depends on how much information you want to store, and what the user can do once he/she already voted for some post,
I would recommend using both, to keep flexibility for the user to like (like in Facebook) so he can unlike something and use the transaction with number to keep it scalable.. so if a post gets 1,000,000 likes you don't have to count the 1,000,000 likes every time someone loads the post

Resources