Firebase,iOS: Appending key-value pair into a child node - firebase

I have the following User Table structure in Firebase
As you can see in the user that I have opened, I have a Posts section, inside this post section holds the Id's all articles which have been posted by this user.
The issue I am facing is as follows:
When the user creates a new article it's saved within the Posts Table, after the save I return the newly generated ID which I then pass on to the user table, I trying to insert the newly created ID into the post section of the user, so I assumed the URL would be something like this:
Users/{UserId}/Posts
However all this does it create a new section called posts, it doesn't actually insert the record into the given area.
My code which isn't working is as follows:
let linkPost = [childautoID: true]
FIRDatabase.database().reference().child("Users/\(UserId)/Posts").child(UserId).setValue(linkPost)
FYI the two id's that are currently inside Posts I added manually.
I've also tried the following:
FIRDatabase.database().reference().child("Users/\(UserId)/Posts").setValue(linkPost)
However all this does it remove all existing Id's and then inserts the new id.

I prefer something like this. This automatically append the data without fetching first
FIRDatabase.database().reference().child("Users/\(UserId)/Posts").child(UserId).setValue(true)

To append a key-value pair in Firebase Database child node use this :-
Make a Firebase Database Reference to the Posts node of that currentUser FIRDatabase.database().reference().child("Users").child(FIRAuth.auth()!.currentUser!.uid).child("Posts")
Check if Posts node exists in your user's DB, If not then create one by :- parentRef.setValue([postId : "True"]) in else block.
But if Posts node does exist retrieve it as a NSMutableDictionary , set the new object to it, and then store the updated Dictionary to that node.
func storePostsToDB(postID :String!, userID : String! = FIRAuth.auth()!.currentUser!.uid){
let parentRef = FIRDatabase.database().reference().child("Users").child(userID).child("Posts")
parentRef.observeSingleEventOfType(.Value, withBlock: {(friendsList) in
if friendsList.exists(){
if let listDict = friendsList.value as? NSMutableDictionary{
listDict.setObject("True", forKey: postID)
parentRef.setValue(listDict)
}
}else{
parentRef.setValue([postID : "True"])
}
})
}
Calling the function:-
storePostsToDB("yourPostID")// If you want to store in the currentUser DB
storePostsToDB("yourPostID", userID : otherUserID)//If you want to store the post in some other users database with uid `otherUserID`

Related

Flutter getting a specific field from firebase and assigning it to list

I am trying to query data from firestore and assign it to a List.
My users collection is as follows
List<String> emailList = ['Select email', 'email1', 'email2'];
I am trying to populate the above emaillist with the emails of persons such that the list is populated by emails of the persons where the groupId is equal to groupId of current user.
I tried querying by Firebase.instance.collection.where but it gets an error saying it cant be assigned to a List.
Any idea on how to do that?
It sounds like the issue is how you are adding to the list. You have to loop through the snapshot query and for each document, add to the list.
Firestore.instance.collection('users').getDocuments().then((snapshot) => {
snapshot.documents.forEach((doc) {
emailList.add(doc.data['email']);
})
});
Hope this helps!

Create documents, sub collections in Firestore via flutter on screen loads

I want to achieve is when flutter screen loads a document should create in firestore in following order.
Document > Sub Collection > Document > Data Fields
I manage to create documents and sub collections in above order, but the first Document appear in italic. That's because the child collection, documents creating before parent document created.
But I couldn't able to fix the issue. I've modified the code now it's not even creating the document. Before this It created in italic mode. Now it's not at all.
Here is the code.
getCurrentUser().then((user) {
DocumentReference todayReference = firestoreInstance.collection('attendance').document(todayDate);
firestoreInstance.collection('profiles').where('user_id', isEqualTo: user).snapshots().listen((onData) {
onData.documents.forEach((f) {
CollectionReference todaySubCollection = todayReference.collection(f.documentID);
DocumentReference attendanceReference = todaySubCollection.document(f["name"].toString().toLowerCase());
Map<String,dynamic> mapData = new Map<String,dynamic>();
mapData['attendance_status'] = true;
mapData['in'] = true;
mapData['out'] = true;
firestoreInstance.runTransaction((transaction) async {
await transaction.set(attendanceReference, mapData);
});
});
});
});
Here getCurrentUser() is returning the logged in user id.
Each profiles assigned to a user.
So, What I'm trying to do is, once user logged in a document should create under attendance collection named today's date.
Then looping through each profiles where user_id is matched with logged in user, the matching results will be store as sub collection under today's date with profiles name field.
Then under the name (document), a transaction needs to run to set details like attendance_status, in & out.
Following images will show how previously documents created.
I need to find a way to create documents, collection without in italic mode. Any help would be appreciated.
"Italicized" documents are virtual/non-existent as mentioned in the docs. If a document only has a sub-collection, it will be a virtual/non-existent document. A workaround for this is by writing fields in the document, like what you've mentioned in the comments.

How to access an object into another object in a query database from firebase functions?

I am trying to access to a object into another object in my firebase database, i have a structure like this:
I want to get all the objects that have the email that i send by parameters, i am using .child to access to the childs into my object but i am not success with the query, this is my code
$ ref_db.child("/groups").child("members").orderByChild("email").equalTo(email).once("value", (snapshot)=>{
console.log(snapshot.val());
});
The snapshot.val() always is undefined.
could you help me with the query?
One efficient way to get "all the groups that have that email inside the members object" would be to denormalize you data and have another "main node" in your database where you store all "members" (i.e. their email) and the "groups" they belong to.
This means that each time you add a "member" node under a "group" (including its email) you will also add the group as a child of the member email, in this other "main node".
More concretely, here is how would be the database structure:
Your current structure:
- groups
- -LB9o....
...
- members
- -LB9qbd....
-email: xxxx#zzz.com
- -LBA7R....
-email: yyyyy#aaaa.com
And the extra structure:
- groupsByMembers
- xxxxxx#zzzcom
- Grupo1: true
- yyyyy#aaaacom
- Grupo1: true
- Grupo2: true
- bbbcccc#dddcom
- Grupo6: true
- Grupo8: true
Note that in the "extra structure" the dots within an email address are removed, since you cannot include a point in a node id. You will have to remove them accordingly when writing and querying.
This way you can easily query for the list of groups a member is belonging to, as shown below. Without the need to loop several times over several items. This dernomalization technique is quite classic in NoSQL databases.
const mailToSearchFor = xxxx.xx#zzz.com;
const ref = database.ref('/groupsByMembers/' + mailToSearchFor.replace(/\./g, ''));
ref.once('value', snapshot => {
const val = snapshot.val();
for (let key in val) {
if (val.hasOwnProperty(key)) {
console.log(key);
}
}
});
In order to write to the two database nodes simultaneously, use the update method as explained here https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields
This is because you have a random key before members, you need to go through the path and not skip a node, to be able to access the values:
ref_db.child("groups").child("-LB9oWcnE0wXx8PbH4D").child("members").orderByChild("email").equalTo(email).once("value", (snapshot)=>{
console.log(snapshot.val());
});

Delete from Firebase Realtime Database

I have this structure of my database :
Posts
-> Key
-> PostId
-> PostName
-> PostDescription
-> PostDescription2
-> Location
-> Author
-> Date
-> Key
->
->
....
Somehow the field PostDescription has been duplicated in PostDescription2, I have n such nodes and I want to delete all entries of PostDescription2 from all the nodes. How can I do this ?
I did some search on google, but most articles tells about how to delete a child node or fields inside them using some logic in query. Also, I am a bit new to firebase.
You will need to execute this function ones. (Seams so) A sample of deletion code may look like into ie: posts path:
var dB = firebase.database();
var dBRef =dB.ref('posts');
dbRef.once('value', snpsht=>{
snpsht.forEach(dp =>{
var key = dp.key;
dB.ref('posts/' + key + '/PostDescription2').set(null);
})
})
This will delete all PostDescription2 field with setting value null. Consider that posts path is not a big data to avoid blocking the code. If so, you may get data with limitToLast option like:
var dBRef = dB.ref('posts').orderByChild('PostDescription2').limitToLast(1000);
This command will order the list by PostDescription2 and null value for the specified child key come first. and we collect from last 1000 items with above code.

How to get user specific data in Firebase Swift 3

I want to retrieve data of current user in the application. How can I do that. ?
Here is my current user's firebase id :
And my table node is :
Here it is clear that my uid and nodes title are different. So how can I get particular user's data.
My code till now:
self.ref = Database.database().reference()
let userID = Auth.auth().currentUser?.uid
self.ref.child("member").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists() {
// handle data not found
return
}
})
You are getting different IDs, because the first one Wnlxl... is the userID and the other -KVvR664... is an autoID.
You have set .childByAutoID following the member, if you want to retrieve the data of the current user then, you have to put userID following member.
Then you can easily retrieve the user's data by userID because each and every detail will be saved under userID.
Hope this code will work for you.
let ref : FIRDatabaseReference!
ref = FIRDatabase.database().reference()
ref.child("member").child(user!.uid).setValue(["name": self.fullName.text!, "email": self.email.text!, "mobile": self.mobile.text!, "doj": self.doj.text!])
Your Firebase screenshot is incorrect I think - your code will work fine, but how you create these members are wrong.
When creating the members you are saying .childByAutoID which you should be using Auth.auth().currentUser?.uid. If that makes sense. Let me know.
Edit: to create a user with userUID data in the node member do the following:
if let userUID = Auth().auth.currentUser?.uid{
ref.child("members/\(userUID)").setValue(*YOURMEMBERINFODICTIONARY*)
}

Resources