Organize groups with timestamps in NoSQL - firebase

The bounty expires in 1 hour. Answers to this question are eligible for a +300 reputation bounty.
Fredyonge wants to draw more attention to this question.
I have a question regarding the formatting of data in a nosql database
I have the following use case:
n User can be in
n Groups where each user has
1 time goal per day
1 time he is currently tracking (which increments during the day)
The goal: Each user works toward a goal (in minutes) per day and can see each others progress.
The hardest part for me is the time goal. I have no idea how to structure that.
My thinking right now:
Users
unique_id:
name: user1
timeTracked:{
{11.02.2023:45}
}groups:[group1, group2, group3]
groups
groups1:
members:{user1,user2...}
time:{
22.02.22:{
user1:43
user2:60
}....
goals:{
22.02.22:{
user1:80
Would that be a sensible way of structuring the data? That would make it quite hard to track if users have achieved their goals in the past: If I only have a timestamp from 05.02.22 because the user didn't change their current goal, I would have to extrapolate it for the days up until 11.02.22

I would suggest to make a separated collection for each user's time goals.
The separated collection will store the users' time goal for a specific day.
user_id: "user1"
date: "2020-02-15"
goal: 54
You will be able to track each user's progress towards their goal for each day easily, even if they don't update their current time tracking.

Related

Firestore best practices: Make one document per entry or group entries of a given month within one document

I am doubting myself on how I should approach this problem.
My users are able to record many parts of their day, including activities, mood, health measurement (heart bpm, glucose), exercise, meals.
I originally thought that I should create one document per entry (i.e. one entry per day). However, when displaying data to the user it rarely occurs on a day by day basis but more on a month by month (charts).
Should I model my Firestore DB in relation to my views or would it be better to just save each entry for each day and then just query?
I am just thinking that it will be more efficient in many parts of the app to have the entries grouped by month than by day.
Am I thinking this right or is there really no benefit? (i.e. maybe the amount of data transferred offsets the costs of unnecessary queries).
If you plane to save each entry for each day and then just query and query to find the result. The more document you'll have, the more document you will query and it will increase you're read/day and so may be more expensive than in a month by month.
To answer your last question :
Let's take an example : if you have a collection with 100 documents.
And you want to query 20 of it.
It will only count as 20 read and not 100 as we might expect.
Just to remind that with firebase you can read up to 50k/day for free, after this limit is it 0.06$/100k read.
I hope it will help you.
Have a nice day !

Making a leaderboard with Firebase Realtime database and Unity

I am making a leaderboard by using firebase realtime database, unity and facebook ( for profile pic and name )
But I am struggling, I am not sure about the way of doing that. I want to display multiple leaderboards -> All time WORLD / REGION / FRIENDS score, monthly WORLD / REGION / FRIENDS and weekly one.
I know I can use cloud functions to reset weekly and monthly leaderboards.
But how can I store world and region scores ?
Now I just have this ->
https://cdn.discordapp.com/attachments/440873502535450627/821361474353889320/ld.JPG
Thanks to that, I can easily get region leaderboards getref.getchild users . getchild france and then orderbyvalue . limittolast ! this is good !
The problem is how could I get world leaderboard ? ( I have other countries ) I am so lost...Do I need to make another structure for my leaderboard ?
There are a number of considerations that you might put into this including pricing, how much you trust the client, &c. Generally, with a NoSQL database like Realtime Database, you might have a lot of redundant data to make up for the fact that your ability to query is limited. It's also really easy to pull in a lot of data by mistake, so you'll see a number of best practices around keeping your database shallow.
With that said, I think I might recommend reorganizing your data a little bit. For example:
Have one node named "users" with all of your users in there. Each "user" in users should be placed in a node that's simply the userid (which makes security rules easier to write), and here you can place the all time score, monthly score, and weekly score. I'd also recommend storing the time you got that score (using ServerValue.Timestamp) so you don't have to worry about going through your users and deleting all the old scores. If your weekly timestamp isn't this week, you know to ignore/overwrite it (obviously, time is hard, so you'll have to work out what a "week" means to players of your game wrt time zones &c).
I'd also put an array of all a user's "friends" under this user node by their user id. That way, when you go to look up friends, you just just ask for "users/" explicitly there.
Now for regional and world leaderboards on monthly and weekly cadences, I'd just copy everything you want to display into that leaderboard node (say username and score) and add the uid if you need to attribute it back to a user (say if you want to click on that score and see their all time record). So if a user lives in France and they get a weekly high score for them, I'd first write that user's "users/" node with the weekly score and timestamp, then I'd go out to the weekly leaderboard for France and add the new score if it qualifies (ie: don't add it if you're only tracking the top 10), then go out to the world leaderboard and add it there.
How you do this copying is up to you. You could make it the client's responsibility with security rules just making sure they're well behaved - which would probably be fast and cheap but might get weird if they go offline partway through updating. You could use a Firebase trigger that would listen for a user updating their node and copy the data out to the respective leaderboards (this would be more expensive since you're paying for Cloud Functions time and a bit slower but will always work once the user node is updated).
A final note is that for, say, weekly leaderboards. I'd have a node that says "this is France's weekly leaderboard right now" and have all clients read that first before figuring out where to write. That way, at a time you decide for when the week turns over, you can change that node and just have people start writing somewhere else. You can then keep the old leaderboard up for some time (ex: maybe you want to see who changed between this week and last), and you can delete it at your leisure after you're sure that all players have their score in (ex: over slow internets, disconnects, &c).

Unique Users in Google Analytics

I'm trying to get all unique visitors for a selected time period, but I want to filter them by date on the server. However, the sum of unique visitors for each day isn't the number of unique visitors for the time period.
For example:
Monday: 2 unique visitors
Tuesday: 3 unique visitors
The unique visitors for the two days period isn't necessarily 5.
Is there a way to get the results I want using the Google Analytics API (v3)?
You're right that Users aren't additive, so you can't simply add them day by day. There are several ways around this.
The fist and most obvious is that if you've implemented the User-ID you should be able to straight up pull and interrogate the data about which users saw your site on which days.
Another way I've implemented before is to dynamically pull the number of Users from the Google Analytics API whenever you need it. Obviously this only works if you're populating a live web dashboard or similar, but since it's just the one figure you're asking for, it wouldn't slow down the load time by much. Eg. if you're using a dashboarding tool such as Klipfolio, you may be able to define a dynamic data source, and query Google whenever you needthe figure (https://support.klipfolio.com/hc/en-us/articles/216183237-BETA-Working-with-dynamic-data-sources)
You could also limit the number of ways that the data can be interrogated, and calculate all of them. For example, if you only allow users to look at data month-by-month or day-by-day, then you only need those figures.
Finally, you can estimate the figure with reasonable accuracy by splitting it into two parts. New Users are equal to New Sessions (you're only new on your first Session), which is additive, so that figure can be separated out and combined as required.
Then, you could take a rough ratio of new to returning Users (% New Users) from, say, 1 year of data, and use that with the New Users figure to generate an average on any level.

Last “end date” with data in Analytics

I'm using "Reporting google Analitics API" and I can’t find information about what the last “end date” with data in Analytics is.
For example, let's suppose you want to retrive the last month’s data.
When do you have to perform the query?
The first day of the current month?
...or the second one?
...or maybe the third one?
And only another question: are the returned data for days in pacific time?
Google Analytics API is supposed to have access to the same data you have in the interface.
Google says that data can take up to 24h to process. The time it takes to really update the data depends on the type and size of the account. Small accounts are updated multiple times a day and can have data available in just a few hours. Once you reach 1M hits a month you are moved to a different mode where the data on your account is updated only once a day. Google Analytics Premium customers have updates more often even for large ammounts of traffic.
There's no way to tell through the API what is exactly the time of the last hit processed. You can query the data for today by the hour and see for yourself though.
Usually you don't care and just want to make sure that the data you're querying has been fully processed for that day.
So if you query data for yesterday there's a chance it has not being completely updated, for example if it's midnight the data for yesterday is just a couple minutes ago and probably haven't been completely processed yet. The safest bet in this case is to query data for 2 days ago.
So if today is 2012-06-15 and you want to get 1 month of data a safe approach is to query data with start-date=2012-05-13 and end-date=2012-06-13. This will most of the time give you data for days that have been fully processed, but it's not 100% safe as well. Google Analytics have had outages in the past where data took longer than that to process, these are not usual though. When you get the data out it's really hard to tell just for the API if the data for those days have been fully processed or not, using the 2 days ago isea you just make it more likely that it is.
The days are aggregate following your timezone settings configured on the Google Analytics profile.

When filtering search results by date, should time zone be crtieria for the date?

We have a website that has a large number of events that have dates and times created by admins. Admins choose a time zone for each date time entered, and they are stored in UTC time. We are trying to support a global audience, and be completely localized in terms of dates.
We have a search page, that allows dates to be entered as search criteria.
So users could say, show me all events between "12:01 AM July-1-2011" and "11:59 PM July 10-2011".
I'm trying to figure out what the best approach is to determining what time zone to consider the date filter criteria in.
Force end users to select a time zone when creating a date filters. This is cumbersome, and our designers our pushing back. It is what I would prefer.
Assume the the entered dates are in the users "preferred" time zone, which is set upon logging in.
Store times in Local time, without converting to UTC. This way the end users are searching in the admin created date. I hate this idea, i need help explaining why this is bad.
Please help!
Second option is possible solution to your problem. And it is probably the best.
Possibly you could get current time zone offset from web browser (with JavaScript) but the problem is, there are certain time zones that currently have the same offset but Daylight Saving Time switches on different dates, therefore search result would be inaccurate. By having User to choose his/her prefer time zone and storing that information in the profile, you could always present correct dates and times, as well as use this information for searching. However, I would add an information near search box, so that end User would know what time zone this refers to (with JavaScript that would be obvious: the current one, with profile User might forgot).
BTW. Time zone information is best to show as "UTC+02:00 (Warsaw, Zagreb, Skopje)" instead "Central European Time"...
As for other options:
1. Too much clicking. As well as "don't make me think, I want to have it in my local time zone, isn't that obvious?".
3. Local times will not be comparable against each other. You will soon end up with two different dates referring to the same point in time (at least in terms of the numbers). Really bad idea.

Resources