In the below image I have messages in my app, yet when a user say updates their profile image or name the data below becomes stale data. I have come across "Firebase Functions" and see that I can keep this data in-sync if I use Firebase Functions. Yet, only knowing Swift I am unsure how to implement Firebase Functions to keep my messages in-sync which the changing data in the user profiles. Can someone help me point in the right direction on how I implement this into my project? Haven't found any sample code in swift or any tutorials for that matter. Any help is greatly appreciated!
Based on the comments and the structure in the question, the reason the data is becoming stale is due to how the data is stored in Firebase.
One option is that when a message is sent, a node is written with the message and then a reference to the senders info. That keeps everything fresh and up-to-date at all times
So say we have a users node with users stored with the users UID as the key to each node
users
uid_0
user_name: "Peter"
user_age: "32"
gender: "Male"
business_name: "Peter's Plumbing Place"
url: "http:...."
type: "Customer"
uid_1
user_name: "Ralph"
user_age: "47"
gener: "Male"
business_name: "Ralph's Repair Room"
url: "http:...."
type: "Employee"
then we have messages
messages
msg_0
msg_text: "Here's a message!"
from_uid: "uid_0"
to_uid: "uid_1"
timestamp: "20180110"
Then, user uid_1 adds a query observer to the messages node for any messages where to_uid is uid_1 so they are notified of the incoming message. When they receive it, they will also know it was sent by uid_0 and can pull up their name, profile image, age etc.
That way, all data is kept in sync and current and no stale data exists.
This is a typical implementation of a structure for a messaging app.
Related
For about a year now, I've been running a social iOS app on a parse server with thousands of users. All my data are stored in a MongoDB. The thing is, the structure of my database has to be improved. For example, the current "Following" system has to be changed in a way that it is gonna be completely different.
My question is, what is the best practise of making that change, considering that not all of my users are going to do the update? How can I be sure that there will be no confusion with the data between the old and the new users?
Edit:
Current Following system:
Here, every time I follow someone, I find the "user" and I append my userId, to his "followers" array...
|objectId <String>| -- |createdAt <Date>| -- |user <Pointer _User>| -- |followers <Array>|
New Following system:
Here, every time I follow someone, I create a new object, where "following" is the current user and "follower", is the user I just followed...
|objectId <String>| -- |createdAt <Date>| -- |following <Pointer _User>| -- |follower <Pointer _User>|
If I'm looking to have posts that can can be replied to, which is a better structure?
1)
posts
908239409234
postText: "Whats up peeps?"
replies:
09283049830294: true
a9s0dif09iasd9: true
replies
09283049830294
text: "Nm breh"
imageURL: nil
a9s0dif09iasd9
text: "Nm breh"
imageURL: nil
or 2)
posts
908239409234
postText: "Whats up peeps?"
replies:
09283049830294
text: "Nm breh"
imageURL: nil
a9s0dif09iasd9
text: "Nm breh"
imageURL: nil
I see so many examples of databases that look like #1 where you store references to posts stored somewhere else to support flattening, but I don't see any advantages to not just going with option 2 if it can be done?
If the user is joining in on a post, they'll have the posts uid, and they can just add in under the "replies" with an autoID.
TL;DR, is it better to go with the flatter method or the method that is seemingly more efficient and requires searching through less information? Is there any reason to not go for option 2?
I would go with no. 2.
The reason is that with no. 1 you will have to do a query to get the reply data based on IDs.
With firebase it is always better to write more and read less.
It depends on whether you will reference replies at some points later. If your replies only relate to your post and no more, then option 2 is optimal because you will not need to fetch the replies. However, if you would like to have more complex feature that will query for replies that relate to some users for example, it will be better to store a reference to each reply as option 1. This is from experience with my app that kept growing and at some points, it is too slow to fetch a node because it has too many children, grandchildren, etc. and I had to flatten the database to make it fetch faster. I would suggest to think about the architecture of your app carefully.
So far on my firebase I have something like:
Users
293840ajldkjfas0d9
username: Jill
09283049802930laks
username: Jack
I'm basically going to just have a text field and when someone hits the "add" button, a search through firebase gets done to make sure that username exists, and go from there on connecting the two as friends.
My question is I'm not understanding how I would sort through my data if it's structured like this? I might be totally missing something but is there a way to search through what I have now and say "Go to my users reference, go to through each UID and pull out the username and see if it matches what the user put in the text field, and if so grab the UID connected to the username"?
I'm almost thinking I need to have an entirely separate branch? that I have in addition to what I already have that looks like
Usernames
Jack
09283049802930laks
Jill
lasdjf9j09u90320j09
Which would then allow me to just go to my usernames and go through and check through the values inside that (jack/Jill) and then if it exists then pull that uid out of the username.
1) Do I need both of these branches or is there a way to accomplish what I'm trying to do with just my first?
2) How exactly do I check for that match? Would a query be used or just checking for Null somehow?
3) Is this even the right way to go about doing this? I've found little to no information on friends lists online so this is just all an assumption.
Any help is appreciated!
Using the below structure, you can check if a user exists with a single query. Here's all the code you need:
This is the db structure:
Users
293840ajldkjfas0d9
username: Jill
09283049802930laks
username: Jack
Here is the code:
var usernameEntered = self.usernameField.text!
var databaseReferenceQuery = self.ref.child("users").queryOrderedByChild("username").queryEqualToValue(usernameEntered).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if ( snapshot.value is NSNull ) {
// No user :(
} else {
// User exists! Do stuff!
}
}, withCancelBlock: { (error) in
// An error occurred
})
Once you have established a user exists, I can think of a few ways to go about getting the uid. The key is to find a place where both the uid and the username are stored.
Option 1:
Create another branch in the users db structure that stores the uid.
Set up this branch when the user is signed up.
Option 2:
Store the username as the displayName in the standard auth system and get the uid from there.
Set this up when the user signs up.
That's up to you.
Response to comments:
You can simply retrieve the key of the user in the table, however this will not allow access to any auth features and will not allow user accounts to be edited in any way.
Examples of situations where this can be useful include updating user info, deleting accounts etc.
The application has certain actions that are recorded for each user and recorded in db table notifications. The table has the following structure:
user_id, notification_type, credit, timestamp
notification_type does not store the entire text of the notification but just stores a short type description.
Later when the user wants to view his notifications I use a helper method from my view to fetch the actual text.
def notification_text(type)
case type_id
when 'flagPositive'
return 'A question you flagged has been marked as correct.'
when 'qAccepted'
return 'A question you added has been accepted.'
when 'qModerated'
return 'You moderated a question.'
when 'flagReport'
return 'You moderated a flag.'
end
end
1) Is this an optimum way to do this?
2) Should I replace the type_description with integer values (say 1 -> flagPositive, 2-> qAccepted) for performance benefits?
3) Are there any best practices around the same that I should be following?
1) This highly depends on your application and requirements. What I can say is that I used this approach sometimes and faced no problems so far.
2) If you see a performance problem with the string lookup, you could do so. A general recommendation is to optimize performance only when really needed.
3) Just google for "Ruby", "Rails", "ActiveRecord" and "Enum". You'll find lots of discussions about different solutions for this kind of problem. There are similar questions on this site, e.g., Enums in Ruby or In Rails, how should I implement a Status field for a Tasks app - integer or enum?
I'm a new to ejabberd but the first thing I noticed is the completely absence of documentation and code comments.
I have many doubts, but the main are:
inside the record jid what is the difference between user and luser, server and lserver, ... and ...?
-record(jid, {user, server, resource,
luser, lserver, lresource}).
what is useful for the record iq?
-record(iq, {id = "",
type,
xmlns = "",
lang = "",
sub_el}).
what is a subscription inside ejabber? a relation between two users?
what is the jid inside the roster?
I know that these questions can be also quite stupid, but I don't really know how to understand without asking, thanks
what is the difference between user and luser?
luser,lserver and lresource are the corresponding parts of the jid after being processed with the appropiate stringprep profile. See https://www.rfc-editor.org/rfc/rfc3920#section-3 . In short, inside ejabberd you will most likely always use the processed versions, and the raw ones only when serializing the JID back to the wire.
what is useful for the record iq?
it make it easier to match on the IQ namespace, id or type (get|set|error) than to retrieve that info from the underling xml each time.
what is a subscription inside ejabber? a relation between two users?
basically, yes. A subscription from user A to user B means A is interested in B presence. But the subscription can be in different states (as the other user has to accept it, etc.). See http://xmpp.org/rfcs/rfc3921.html#sub .
what is the jid inside the roster?
sorry, didn't understand you on that, what do you want to know?