I'm making a Twitter like ios app (just for practicing my programming). I just wondered, because i couldn't find that much online about this stuff, what is the best way (or the most ideal way), to implement following/followers system in Firebase? Like say Mark follows Derek, then Derek makes a tweet, then Mark gets Derek's tweet in his home feed.
Would be great if someone could share their thoughts on this.
One way to do this is: If user A activates the follow-function on user B, the uid of user B gets in the following-node of user A, and user A gets in the followers-node of user B.
After that, there are multiple ways to implement the feed. One way is to go to the tweets of user B and push them to the feed of user A. If user B posts a tweet, loop through his followers and push the key of that tweet to the feeds of his followers. So user A now has the old tweet keys and potential new tweet keys on his feed-node. You can now loop through these keys and get the data from an alltweets-node.
Another way is to let user A loop through his following-node and get the tweets of all the people he follows from their tweet-nodes. You can than join these tweets and sort them by date. A tweet now only has to be posted in the alltweets-node and in the tweets-node of one user, instead of pushing the tweet key to the feed-node of every follower he has.
Just two ways to achieve this, there are certainly more ways to do this, depending on what you want to achieve.
Related
I'm new to Firestore and trying to develop a data model for my app.
Background: I have a dating type of app with 3 primary ways that users will communicate with one another. Liking, dismissing, and commenting user profiles. Users likes & comments are private. In other words, only I can see who's liked or commented my profile (it's not like Social media where everyone can see who's liked a post). I'll need to be able to query users to know who's dismissed their profile so I won't show it to those users again. I'll also need to know who's liked/commented a users profile so I can query which users have liked/commented each other (they've matched)
Users can like many profiles and vice versa
Users can dismiss/skip many profiles and vice versa
Users can comment on many profiles and vice versa
I believe this means I'll need a root collection for likedUsers, dismissedUsers, and commentedUsers
Problem:
For dismissed users, I thought I'd store every single user as a Document of the dismissedUsers root collection and store every user they've skipped as a field/value pair like so...
dismissedUsers/User/user1, user2, user3, etc
The above would create the many-many relationship I want where dismissedUsers can have many users and users can have many dismissedUsers. However, I don't believe it would be scalable as the User Document would grow too large.
Question: How do I create this many-many relationship where dismissedUsers can have many users and users can have many dismissedUsers so that it's scalable and least expensive? And query it?
First of all I would ask myself why I am using Firestore, being a document database, instead of choosing a relational database. I personally love Firestore and highly recommend it. We pick a document database because it is faster and easier to use in many ways. In other ways it is a drawback because you have very limited query power. It sounds to me like your brain is working towards a relational database implementation.
Here is one solution
First of all I would try to avoid storing user data in more than one location to avoid anomalies (of course right). I would have one collection of users where I stored all user data with a unique id (best to use the one that Firestore assigns so I don't have collisions). Within each users document I would link a subcollection for dismissed, liked, been dismissed by someone else, liked by someone else etc.. I would keep a record of all users (just the user id) that they have dismissed, liked, been dismissed by, been liked by etc.. This way I can look up all data for who that user has liked or disliked and display whatever I want to that user accordingly.
Drawbacks
You will have to write twice per like, dismiss etc. Use a batch write to update both the liked and likee data at the same time.
You don't need a collection of users who liked, dismissed, or commented on another users profile. You can have one user collection which stores all users. Inside each user document you can have three array of the user ids of the users that liked, commented, and/or dismissed a user profile. Just make sure that the document ID of the documents inside the users collection matches the user id of the corresponding user.
I am building out an iOS app that requires getting lists of users at different parts of the app(finding users nearby, find users that have similar interest etc) I'm displaying the list of users in collection views/table views.
I have a user structure that contains all of the user data(name, photo, list of interest, location, preferences..etc)
My question is, when I'm getting the list of users from the database, is it more cost effective to use the query function or to use the observe functions? In the list I only need to display the users photo and username. If the user wants to find out more then clicking on the cell will get more data from the larger user data table.
My options
using a query to get the users that meet the criteria for that list(say all users nearby). Then when the user clicks on the cell that interests them, get a snapshot from the database for that specific users.
My thought process is its less costly than pulling back the whole snapshot using the observe functions.
using the observe functions, getting all users snapshot data and only displaying the photo and username. If the user selects a cell send the data to the detail view.
creating a special display structure that contains only items necessary for the collection view/ table view and if the user clicks on a cell call the database again getting all of that users data.
If anyone has a point of view they could share that would be great!
Thanks
Observing in Firebase needed for making instant update, like in chats, when new message appear you need to update message list. So here, for getting list of users that fit your request, better to use queries
I'm trying to develop a trivia app, much like Quiz Up but with multi players.
Here's what I thought of doing:-
Creating a class called 'Game Session' on Parse, that has information of who created it (PFUser.current), the name of the gaming session(name), and the names of users invited(invited_users). Think of this Gaming Session as a closed group where the users interact with each other only.
So there's a createSessionViewController, and a joinSessionViewController.
If User A creates a gaming session (in createSessionViewController) and sends invites out to User B and User C, they get to accept or decline these invites in joinSessionViewController.
Now from what I have researched is that I would have to query through all the objects in the class Game Session (in viewdidload of the joinSessionViewController) and use query.wherekey for eg, User B's object id is in the column "invited_users". If so, I return that Gaming Session's object. Is that right?
If that is the case, is that an efficient way of doing it? Because it seems like if the app gets popular and there are lots of objects in the class, then it could take up a lot of time to get the one object with User B's id.
I hope I made myself clear and you guys understand my question.
PS: I'm sort of new to parse and swift, so if you could give me detailed answers it would be much appreciated.
Your logic is correct but I would also strongly suggest you take a look at Parse-LiveQuery. This tool allows you to subscribe to a PFQuery you are interested in. Once subscribed, the server will notify clients whenever a PFObject that matches the PFQuery is created or updated, in real-time.
https://github.com/ParsePlatform/parse-server/wiki/Parse-LiveQuery
https://github.com/ParsePlatform/ParseLiveQuery-iOS-OSX
Your assumption is correct and that is indeed one way you could go about doing that although it has drawbacks as you mentioned. If you felt like putting more effort into it, you can write JavaScript parse cloud code that executes after an item is saved (for example after a game session is created) and send out silent push notifications with the new objects id to the users who were invited. You could then use that push notification data to know the exact ids instead of having to query for them. This is much more advanced though. For whatever your app is, the simple route of having a model query the data on load should be fine. If you find yourself in a situation where performance is hindered due to this, well then congratulations.
I'm working on an iOS app which at one point displays a feed of information items to the user, that contain information about other users. These feed items are stored on a server that I run as well. I want to add a functionality that allows this user to filter the information and display only items of his facebook friends. It seems to me that there are three ways to achieve this
1
Client fetches all items.For each item run that FB SDK query /user-id/friends to determine friendship
2
Save all of the facebook ID's of the users friends on the client (each set time),and after fetching all items, determine if item is posted by friend with comparison to local database of friends.
3
The server with the feed items would run the query in the backend, and filter the content it provides to the client
Each of these has it's weakness and advantages, but I'd like to hear which is the preferred and "best" overall. I'm trying to achieve something like VENMO's home feed functionality if that makes sense.
Thanks for the help!
This question is very similar to this one, however there are no answers on that one. I posted this one with more clarity in hopes of receiving an answer.
According to this presentation, Twitter incorporates a fanout method to push Tweets to each individual user's timeline in Redis. Obviously, this fanout only takes place when a user you're following Tweets something.
Suppose a new user, who has never followed anyone before (and conversely has no Tweets in their timeline), decides to follow someone. Using just the above method, they would have to wait until the user they followed Tweeted something for anything to show up on their timeline. After some observation, this is not the case. Twitter pulls in the latest Tweets from the user.
Now suppose that a new user follows 5 users, how does Twitter organize and push those Tweets into the user's timeline in Redis?
Suppose a user already follows 5 users and they have a fair amount of Tweets from these users in their timeline. When they follow another 5 users, how are these user's individual Tweets pushed into the initial user's timeline in Redis in the correct order? More importantly, how is it able to calculate how many to bring in from each user (seeing that they cap timelines at 800 Tweets).
Here is a way of how I would try to implement it this if I understand well your question.
Store each tweet in a hash. The key of the hash could be something like: tweet:<tweetID>.
Store the IDs of the tweets of a given user in a sorted set named user:<userID>:tweets. You set the score of the tweet as a unix timestamp, so they appear in the correct order. You can then get a list of the 800 most recent tweet IDs for the user with the instruction ZREVRANGEBYSCORE
ZREVRANGEBYSCORE user:<userID>:tweets +inf -inf LIMIT 0 800
When a user follows a new person, you copy the list of ids returned by this instruction in the timeline of the follower (either in the application code, or using a LUA script). This timeline is once again represented by a sorted set, with unix timestamps as scores. If you do the copy in the application code, which is perfectly acceptable with Redis, don't forget to use pipelining to perform your multiples writes in the sorted set in a unique network operation. It will greatly improve the performances.
To get the timeline content, use pipelining too. Request the tweets ID, using ZREVRANGEBYSCORE with a limit option and/or a timestamp as lower limit if you don't want tweets posted before a certain date.