add data to firebase realtime if not exists - firebase

coming from a SQL background I am still getting used to Firebase.
If I have a node for customers and I allow Firebase to create an id by using the "push" method, how do I take a customer and then only push if it doesn't already exist with the same email address and if it does, then update it?
I know set will create or update if I have a specific node (ie each node is identified by, say, the email address) but in this case I want to push if it doesn't exist and presumably set if it does. What's the neatest syntax for doing this?
thanks
Phil

First, Firestore is recommended for projects going forward. More features.
Note that firebase auth has this email duplication functionality baked in already. So, you might be spending effort on a feature that is already done for you. See auth/account-exists-with-different-credential
Finally to answer your specific question:
The way I do that is to chain the write after a read (.then). The read seeks to fetch the node. After the read if whatever field exists or === myString then you know it's already there.

Related

How to check on Friends presence in React Native Firebase

I'm working on an app where I need to show the friend's presence ( not all users ), as you can see in the picture below. I read the docs of Firebase, they mentioned about users presence but they don't mention any thing about this scenario. If I use all users presence method then what will I do if the users are more than 1000? it gets the data downloaded on every change which I don't want.
There is an idea if I add multiple listeners for every friend then it will be efficient or not, if not then what will be the best practice for it.
Thanks

Human readable equivalent of Firebase Uid [duplicate]

This question already has answers here:
Firebase android : make username unique
(4 answers)
Closed 2 years ago.
In my app, user should be able to connect with each other. So to identify each other, they should have some human readable property, which they can share easily. I was wondering if there is any way that, I could have a Human readable "username" similar to Uid?
I was initially planning to save an Email-id of the user in the database, but as it can change, this approach is not recommended. Also, this approach will fail if user logs in using their phone number.
So, is there any in-built Firebase mechanism to this? What are the best practices / design patterns here? What is the commonly used approach in Firebase world, when it comes to 'identifying each other' or 'sharing'?
It's similar to my answer here.
You need to keep a separate node in firebase realtime database regarding that.
So if your user tries to connect with any other user name user123, you will need to find the node user123 in database and read the UID which will be stored inside and then proceed to your further actions.
Alternatively to make it less lengthy, you could use usernames instead of UID, so there is no question of UID in the application but you will need to take care there are no same usernames and could increase complications.
I'll prefer the first method. Do let me know if you need more assitance.

Reading list with Dialoglfow fulfillment from Real-Time Database

I am creating a chatbot using Dialogflow and Dialogflow's Inline Editor (for Cloud functions and Firebase database "Real-Time Database"). I will integrate this chatbot with Google Assistant.
I have to read a list from the database, wherein the list has several children, few of them have sub-children, and few of sub-children have sub-sub-children. Because the output is a list and consists long-text, it will take too long to speak all data at once. So I would like to output one child from the list and ask the user for permission (Yes/No) as "Do you want to read the next?". If the user says "Yes", I will continue reading likewise until the end. And if the user says "No", I will trigger an event. Asking for the permission from the user is true before reading a child, even sub-child, and even sub-sub-child.
The approach that I have taken involves creating a separate DB record for each user when they first request the list, to keep track of where they are in the list. When the user says yes, get user’s current item id from the database, get the next item in the list (return it to the user via agent.add) and then update the user’s DB record to the next item’s id and so on until the user reaches the end of the list. After agent.add(), ask for the permission from the user by agent.setFollowupEvent(). If the user says no, just reset/delete the DB record for that user.
Few questions I would like to ask:
How will I identify each user as an individual: by some id, session, or something else?
When I run the below code in return cloud function, agent.add is overridden by agent.setFollowupEvent. How do I stop this?
agent.add('I will print the list here!');
agent.setFollowupEvent('SOME_EVENT'); //invoking an intent to ask for the permission.
You have a few issues you're trying to raise here, in addition to the one you're dealing with. Looking at each:
How can I stop setFollowupEvent() from overriding the message I've set?
You don't. The entire point of setFollowupEvent() is to switch to a different Intent instead of the one that is currently being processed.
Most of the time you think you want setFollowupEvent(), you probably don't. Don't use it.
So how can I add the question at the end of what I'm saying?
Just ask it.
Really, it is that easy.
You can either include it in the string you're sending to agent.add(), or (depending on the details), you can do a second add() with the prompt.
But don't I need to trigger an Intent to get the answer?
No. That isn't what an Intent is for.
Intents capture what the user is saying, not what you are asking or what your agent is doing. Your fulfillment does something based on both the Intent that is triggered as well as the rest of the state that you know about the conversation. But the Intent is just one bit of that information.
You mentioned user state. How can I keep track of the user state during the conversation?
Since it looks like you're using the dialogflow-fulfillment library, the easiest way is to store your state in the parameters in a Context with a very long lifespan (or that you keep renewing).
So the first time your fulfillment is triggered, you can check the Context. If the Context or ID aren't there, then you would generate a random user ID and store it in the Context. Subsequently, you would use this ID to look up the user's information in the real time database.
If I'm doing this work, do I need the database?
Nope! If you are just storing a little bit of information about the user, and the information will just last the lifespan of the conversation, you can store all of it in Context parameters directly. You do need to make sure that these parameter names don't conflict with any parameters that your Intents have, but otherwise these will last las long as the Context does.
If you need to store information about this person in between conversations, then you will need to look into other methods. There is a User ID available for Actions, but this is deprecated and scheduled to be removed. There are also session storage and user storage fields that the Assistant makes available, but these are a little tricker to use using the dialogflow-fulfillment library if you don't need them.

Best way to structure related data in firebase/firestore and manage updates?

If I have User and Profile objects. What is the best way to structure my collections in firestore given that the follow scenarios can take place?
Users have a single Profile
Users can update their Profile
Users can save other users' profiles
Users can deleted their saved profiles
The same profile can't be saved twice
If Users and Profiles are separate collections, what is the best way to store saved profiles?
One way that came to mind was that each user has a sub collection called SavedProfiles. The id of each document is the id of the profile. Each saved Profile only contains a reference to the user who's profile it belongs to.
The other option was to do the same thing but store the whole profile of each saved profile.
The benefits of the first approach is that when a user updates their own profile there's no need to update any of the their profiles that have already been saved as it's only the reference that is stored. However, attempting to read a user's saved profiles may require two read operations (which will be quite often), one to get all the references then querying for all the profiles with those reference (if that's even possible???). This seems quite expensive.
The second approach seems like the right way to go as it solves the problem of reading all the saved profiles. But updating multiple saved profiles seems like an issue as each user's saved profiles may be unique. I understand that it's possible to do a batch update but will it be necessary to query each user in the db for their saved profiles and check if that updated profile exists, if so update it? I'm not too sure which way to go. I'm not super used to NoSQL data structures and it already seems like I've done something wrong since I've used a sub collection since it's advised to keep everything as denormalized as possible so please let me know if the structure to my whole db is wrong too, which is also quite possible...
Please provide some examples of how to get and update profiles/saved profiles.
Thank you.
Welcome to the conundrum that is designing a NoSQL database. There is no right or wrong answer, here. It's whatever works best for you.
As you have identified, querying will be much easier with your second option. You can easily create a Cloud Function which updates any profiles which have been modified.
Your first option will require multiple gets to the database. It really depends how you plan to scale this and how quick you want your app to run.
Option 1 will be a slow user experience, while all of the data is fetched. Option 2 will be a much faster user experience, but will requre your Cloud Function to update every saved profile. However, this is a background task so wouldn't matter if it takes a few seconds.

Firebase security rules based on currently existing values

I'm trying to implement a rule in my firebase DB that dis-allows a user to update a posts likes value if it doesn't already exists in their fanned data. Consider this file structure.
Notice how there is a full dictionary of values. Given conditions in my app, users have the ability to write to the likes value in this dictionary. In the event that this dictionary of data Does not already exist, I want to prevent users from writing to the likes value so this doesn't happen.
This is the security rule I have currently in place but I am not sure how I can solve this problem.
I have already looked at the documentation and watched David East's video on securing your Firebase DB but I am still lost.

Resources