How we get message of particular user to another in Firebase - swift

I want to get message sent from a specific user to another. I am unable to achieve this. When I use the following code, I get the message from receiver. What I need is to get message particular recieverid to particular senderid.
My Database Snapshot
Here is my code:
Database.database().reference().child("chats")
.queryOrdered(byChild: "receiverid")
.queryEqual(toValue: "xEdACTcUWeOwrdIqjxeP5t5y4Kg2")
.observe(.childAdded, with: { snapshot in
let msgDict = snapshot.value as! [String: Any]
print(msgDict)
})

When using Firebase, you should structure your data to match the need of your views.
It looks like what you're trying to do is execute a query based on 2 properties and the Realtime Database can't do that yet. I recommend changing the structure of your data. Use your senderId as the key to each chat.
This way you'd have something like this:
"chats"{
"-L1RW456789":{
"messageKey":{
"name":"ddddd",
"receiverid":"xEdACTcUWeOwrdIqjxeP5t5y4Kg2",
"sender_id":"-L1RW456789",
"text":"Hello World"
},
"message2Key":{
"name":"eeeee",
"receiverid":"xEdAdasd23123",
"sender_id":"-L1RW456789",
"text":"How are you?"
}
}
}
(You can remove the "sender_id" attribute now, as it is now accessed by getting the key of the message's parent node)
And you'd be able to run your query like this:
Database.database().reference().child("chats").child("-L1RW456789")
.queryOrdered(byChild: "receiverid")
.queryEqual(toValue: "xEdACTcUWeOwrdIqjxeP5t5y4Kg2")
.observe(.childAdded, with: { snapshot in
let msgDict = snapshot.value as! [String: Any]
print(msgDict)
})

Related

How to read values of a child from Firebase Realtime DB?

I am trying to get values from my database. However, I am unsuccessful. Here is what the DB looks like:
Here is what I tried to do, to read the values:
taskRef = Database.database().reference(withPath: "Tasks").child(titleOfTask)
taskRef?.observeSingleEvent(of: .childAdded, with: { (snapshot) in
if let taskDict = snapshot.value as? [String:Any] {
print("Printing ---------> ",taskDict["Description"] as Any)
}
})
but nothing happens. Ideally, I want to read both the description in a different variable and due date into a different variable.
Important Things to know:
"Tasks" is.. you can think of it as a table name.
Alpha, Bravo, Jalabi... etc are all "Task Names" or childs of "Tasks"
Description, Due Date are the values
You're attaching a listener to /Tasks/$titleOfTask in your JSON, say /Tasks/Alpha. That listener is asking to be called for the first child node of /Tasks/Alpha, so the snapshot in your code will point to /Tasks/Alpha/Description. When you then print taskDict["Description"], you are printing the value of /Tasks/Alpha/Description/Description, which does not exist.
The simplest fix is to listen for the .value event:
taskRef?.observeSingleEvent(of: .value, with: { (snapshot) in
if let taskDict = snapshot.value as? [String:Any] {
print("Printing ---------> ",taskDict["Description"] as Any)
}
})
Now the snapshot has all data from /Tasks/Alpha, and thus the taskDict["Description"] ends up being the value from /Tasks/Alpha/Description.

How to unpack multiple levels of nested JSON in Firebase Database

In my app, I would regularly have a JSON topic, for example message, then nested in that is a random ID, then the message text as a string inside the random ID. But, I need to decipher multiple levels of random IDs. Is that possible in Firebase for Swift? This is what I mean:
This is my code:
Database.database().reference().child("app").observe(.childAdded) { (snapshot) in
//app is first in the JSON tree
let dict = snapshot.value as! [String: Any]
let msg = dict["message"] as! String
Obviously this is crashing the app, as it's looking for "Message" in the first RandomID. Is there a solution to this? I haven't found resources for specifically what I'm looking for. Thank you.
You'll want to loop over the children of snapshot as shown here:
Database.database().reference().child("app").observe(.childAdded) { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot //downcast
let dict = snap.value as! [String: Any]
let msg = dict["message"] as! String
}
})
Also see:
Get data out of array of Firebase snapshots
Swift Firebase -How to get all the k/v when using queryOrdered(byChild: ).queryEqual(toValue: )
other questions about looping over child nodes

How to check if a Firebase DB node value is true using swift?

I have the following Firebase DB structure (see pic) which is created when a user sends a compliment to another user.
The compliment is saved under compliments with an auto-generated id
The compliment.key is also saved under users-compliments, under senderID/receiverID/then the "complimentID":"boolean" pair to indicate if it is "active"
I wish to check if an "active" compliment exists before being allowed to send another one to the same user.
But the following query results in a null output even though there is a child node with a value of 1.
What am I doing wrong here?
Query:
REF_USERS_COMPLIMENTS.child(currentUid).child(forId).queryEqual(toValue: "1").observeSingleEvent(of: .value) { (snapshot) in
print("snap: \(snapshot.value)")
}
Console output:
snap: Optional(<null>)
When using queryEqual() you have to combine it with an queryOrderedBy. In your case it would be queryOrderedByValue() because you want to compare the value:
REF_USERS_COMPLIMENTS.child(currentUid).child(forId).queryOrderedByValue().queryEqual(toValue: "1").observeSingleEvent(of: .value) { (snapshot) in
print("snap: \(snapshot.value)")
}
More information about this can be found in the docs.
Try this:
REF_USERS_COMPLIMENTS.child(currentUid).child(forId).observeSingleEvent(of: .value) { (snapshot) in
print("snap: \(snapshot.value)")
if let _ = snapshot.value as? NSNull {
// do your thing
}
}

Get youngest child in Firebase users

I want to find the youngest user in my list of users and load their data: name, profile pict, and current job assignments. I have read the Firebase primer on querying data, but their examples don't work for me because my data is organized differently. I have an additional child layer.
This is my JSON tree in Firebase:
I've tried loading the list of users and then iterating over them to find the youngest user, but that seems like overkill. The Firebase documentation makes me think I should be able to do the query through a Firebase method, like 'queryOrderedByChild' or similar.
I've gone over the old documentation here and the new documentation here, but I'm still left wondering what to do.
So this is my workflow:
The app will find the youngest user in the list of "members" and load their name, profile pict, birthday, etc. They will choose from a list of jobs. Once that user has chosen from the lists of available jobs, the app will load the next youngest user from the list of "members", and so on until all users have been loaded and have been given the chance to select jobs.
I think a better workflow would be this:
Get youngest user by utilizing a Firebase query
Use that query to load that user (image and name)
How would I go about doing that?
EDIT #1: Code I've Tried
func loadExistingUsers(completion: #escaping ([[String : Any]]) -> ()) {
var dictionary = [[String : Any]]()
ref.child("members").observeSingleEvent(of: .value) { (snapshot: FIRDataSnapshot) in
for child in snapshot.children {
let snap = child as! FIRDataSnapshot
if let value = snap.value as? [String : Any] {
dictionary.append(value)
}
}
completion(dictionary)
}
}
And then in ViewDidLoad:
loadExistingUsers { (dictionary) in
var youngestBirthday = 19000101
var userName = "Sophie"
for item in dictionary {
let fetchedBirthday = item["birthday"] as! Int
let fetchedName = item["firstName"] as! String
if fetchedBirthday > youngestBirthday {
youngestBirthday = fetchedBirthday
userName = fetchedName
}
}
print(userName,youngestBirthday)
}
This method returns the youngest user from my list of users, but it seems like an awfully long way to go to get what I want. I have to first fetch the users from Firebase, and then parse the snapshot, then create an array, then sort the array, then get the user name. I was under the impression Firebase could do all that with one query. Am I wrong?
You can get the youngest child using this code: (since your youngest date is the largest number so I am using toLast)
ref.child("members").queryOrdered(byChild:"birthday").queryL‌​im‌​ited(toLast: 1).observeSingleEvent(of: .childAdded, with: { (snapshot) in
if let value = snapshot.value as? [String: Any] {
let name = value["firstname"] as? String
//you can do for other values as well
print(name)
}
})

When retrieving data from Firebase Database, <null> is returned: "Snap (...) <null>"

I'm a relatively new Swift programmer and am using Firebase for the first time so please excuse any misunderstandings I may have and my lack of knowledge about terminology.
I am attempting to retrieve data about a user that is stored in a database (email and username).
The code successfully finds the userID in the database. The userID is then used in order to navigate into the directory containing the username and email. It stores those values in snapshot.
For some reason, when snapshot is printed, it shows the userID but the contents of the directory (username and password) are shown as <null>. I am certain that the directory I am attempting to access and retrieve data from exists and is not empty (it contains a username and email). I wantsnapshot to store the username and email, but printing shows that it is not doing so correctly and I cannot figure out why.
here is my code block:
func checkIfUserIsLoggedIn() {
if Auth.auth().currentUser?.uid == nil {
perform(#selector(handleLogout), with: nil, afterDelay: 0)
} else {
let uid = Auth.auth().currentUser?.uid;
Database.database().reference().child("Users").child(uid!).observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot)
if let dictionary = snapshot.value as?[String:AnyObject] {
self.userLabel.text = dictionary["name"] as? String
}
}, withCancel: nil)
}
}
and here is what is being printed to the console:
Snap (ywU56lTAUhRpl3csQGI8W8WmQRf1) <null>
Here is the database entry I am attempting to reach and log to snapshot:
I'm a new Stack Overflow user and don't have enough experience on the site to be allowed to embed images in posts, so this is the external link
Thanks for reading, any help would be much appreciated!!
Your reference in Firebase is to "users", but you are using .child("Users") in your code. Make sure your lookup matches case to your node. I find it best to create a reference to that node and use it for writing to and reading from.
let usersRef = Database.Database().reference().child("users")
Snap (ywU56lTAUhRpl3csQGI8W8WmQRf1) <null> the portion in parenthesis refers to the end node of what you are trying to observe. In this case it refers to uid!.
if u want to get username or email then you make first the model class for
Example:-
class User: NSObject {
var name: String?
var email: String?
}
then user firebase methed observeSingleEvent
FIRDatabase.database().reference().child("user").child(uid).observeSingleEvent(of: .value, with: { (snapShot) in
if let dictionary = snapShot.value as? [String: Any]{
// self.navigationItem.title = dictionary["name"] as? String
let user = User()
user.setValuesForKeys(dictionary)
self.setUpNavigationBarWithUser(user: user)
}
})`
if it is not finding your asking values, you are asking wrong directory. check firebase db child name it must be exactly like in your code ("Users")