I want to search in firebase through user name - iphone

I am facing an issue in retrieving a data present in node
Dev->Regis->[userId("hjgsfgsdfghd8ydfsw3r")]->UserInfo->{userName:"", email:""}
I am trying the following query
ref.child(kChild).child(kRegistration).queryOrdered(byChild: kUserInfo).queryEqual(toValue: searchText).observeSingleEvent(of: .value) { (snapshot) in
if snapshot.exists() {
}
}
I also tries by making rules but it does make result
"Development": {
"Registration": {
"$user_id": {
"UserInfo": {
".indexOn": ["userName"],
".read": "auth.uid == $user_id"
}
}
}
}
database structure
and ref means Database.refrence()
Please help to sort out this problem.
Thanks.

Assuming searchText is the username value that you want to grab the object for. Firebase requires an orderBy call.
let searchText = //username you wish to fetch
let ref = db.ref('Development/Registration/${userId}/userInfo')
ref.orderByChild('userName').equalTo(searchText).once("value", function(snapshot) {
if(snapshot.exists()){
//whatever you want to do here
}
}

Related

How I can get all of users lists from Firestore?

class UsersViewModel : ObservableObject {
#Published var users = [CurrentUser]()
init() {
fetchUserLists()
print(users)
}
func fetchUserLists() {
FirebaseManager.shared.firestore.collection("users")
.getDocuments { documentSnapshot, error in
if let error = error {
print("Error to get user lists")
return
}
//success
documentSnapshot?.documents.forEach({ snapshot in
let user = try? snapshot.data(as: CurrentUser.self)
if user?.uid != FirebaseManager.shared.auth.currentUser?.uid {
self.users.append(user!)
}
})
}
}
}
I'm trying to fetch all of users in my firestore database, but unfortunately my users array is empty. I don't know what my mistake is.
Please check my firestore screen shot, and give me tips!
Thank you!
You're having an issue with asynchronous code. Code is faster than the internet and you have to allow time for data to be retrieved from Firebase.
Additionally, Firebase data is only valid within the closure following the Firebase call. In this case your code is attempting to print an array before it's been filled.
Here's the issue
init() {
fetchUserLists() //<-takes time to complete
print(users) //this is called before fetchUserLists fills the array
}
here's the fetchUserLists function with where the print statement should be
func fetchUserLists() {
FirebaseManager.shared.firestore.collection("users").getDocuments { documentSnapshot, error in
if let error = error {
print("Error to get user lists")
return
}
documentSnapshot?.documents.forEach({ snapshot in
let user = try? snapshot.data(as: CurrentUser.self)
if user?.uid != FirebaseManager.shared.auth.currentUser?.uid {
self.users.append(user!)
}
})
print(self.users) //we are within the closure and the array is now populated
//this is a good spot to, for example, reload a tableview
// or update other UI elements that depend on the array data
}
}

Iterate through emails in Firebase - Swift

I am currently trying to iterate through all user emails in firebase, however, whenever I run my code, and try to add the "test#gmail.com" user, there is an error. However, when I try to add my current user's email address, "test1#gmail.com", there is a success.
Below is a snippet of my code demonstrating this. B
Below is also an image showing the structure of my current database.
Note that each user's email is under a unique userID under the "users" part of the database.
Iterating through email snippet.
func searchEmails() {
var ref : DatabaseReference
let currentUserID = Auth.auth().currentUser?.uid
ref = Database.database().reference()
let userRef = ref.child("users")
userRef.observeSingleEvent(of: .value, with: { snapshot in
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? DataSnapshot {
userRef.child(rest.key).child("email").observe(.value, with: { snapshot in
print(snapshot.value!)
// print("Other rest is this \(otherRest.value!) value")
if(snapshot.value as? String == self.shareEmail.text) {
SVProgressHUD.showSuccess(withStatus: "Request sent to user!")
}
else {
SVProgressHUD.showError(withStatus: "Email not valid.")
}
})
}
})
SVProgressHUD.dismiss()
}
Why don't you try this, Might turn out to be much less headache.. :-
if self.shareEmail.text != "" && self.shareEmail.text.isEmpty == false{
Database.database().reference().child("users").queryOrdered(byChild: "email").queryEqual(toValue: "somemail").observe(.value, with: {(Snapshot) in
if Snapshot.exists(){
// The email that you have been searching for exists in the
// database under some particular userID node which can
// be retrieved from ....
print(Snapshot)
}else{
// No such email found
}
}, withCancel: {(error) in
// Handle any error occurred while making the call to firebase
})
}else{
//Your textfield must not be empty;.... Handle that error
}
Note : This is only gonna work if Firebase Security rules allow it... so you might have to work on that on your console... Good luck!

Unique usernames in Firebase

I have been trying to implement Chris’ answer here: Can I make Firebase use a username login process? for the Facebook login but I can’t seem to get my head around it.
So far I’ve tried to set conditions on the textField but as Firebase observer works asynchronously, the conditions to check if the username exists in the database won’t work.
let usernameString = usernameTextField.text
let uid = FIRAuth.auth()?.currentUser?.uid
ref.runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in
if var post = currentData.value as? [String : AnyObject], let uid = FIRAuth.auth()?.currentUser?.uid {
let usernamesDictionary = post["usernames"] as! NSDictionary
for (key, _) in usernamesDictionary {
if key as? String == usernameString {
print("username not available: \(key)")
}
else if usernameString == "" {
print("Uh oh! Looks like you haven't set a username yet.")
}
else if key as? String != usernameString {
print("username available: \(key)")
print("All set to go!")
let setValue: NSDictionary = [usernameString!: uid]
post["usernames"] = setValue
currentData.value = post
}
}
return FIRTransactionResult.successWithValue(currentData)
}
return FIRTransactionResult.successWithValue(currentData)
}
Then I tried creating /usernames/ node in the database and set up rules as:
{
"rules": {
"usernames": {
".read": "auth != null",
".write": "newData.val() === auth.uid && !data.exists()"
}
}
}
Now that won’t let me set any username to the database. I get confused in creating rules but my whole point is that I need a sign up flow with the username data that’s unique for each user in the database.
While trying every answer I found in related posts, what worked for me the easy way i.e. without making Firebase rules play a part in it or creating a separate usernames node in the database was to not put an if/else condition inside the Firebase observer but instead to use the exists() method of FIRDataSnapshot.
Now here’s the trick, while I did try only the exists() method with a simple observer but that did not help me. What I did was first query usernames in order, then match the username with queryEqualToValue to filter the query:
refUsers.queryOrderedByChild("username").queryEqualToValue(usernameString).observeSingleEventOfType(.Value , withBlock: {
snapshot in
if !snapshot.exists() {
if usernameString == "" {
self.signupErrorAlert("Uh oh!", message: "Looks like you haven't set a username yet.")
}
else {
// Update database with a unique username.
}
}
else {
self.signupErrorAlert("Uh oh!", message: "\(usernameString!) is not available. Try another username.")
}
}) { error in
print(error.localizedDescription)
}
}
This is the first time out of most of the answers here that worked for me. But for now, I don’t know if this would scale. Post your experiences and best practices. They’ll be appreciated.

Unrecognized selector while removing all user posts from Firebase

I tried to delete all posts that belongs to specific user, however it crashes telling me error:
'-[FIRDataSnapshot removeValue]: unrecognized selector sent to
instance 0x174238c20'
but if I try to po the child, it prints out the child.
That is how I am doing it in Swift3:
FIRDatabase.database().reference().child("posts").queryEqual(toValue: self.currentUser.generalDetails.userName).ref.observe(.value, with: { (snapshot: FIRDataSnapshot!) in
for child in snapshot.children {
(child as AnyObject).removeValue() //This line gives the error.
}
})
That is the child that shold be removed if "username":"currentUser.generalDetails.userName":
posts
-KUaMd3YgJlQvv_P-kdK//This has to be deletod with all its children
content:
likes:
postId:
postImageStringUrl: close
profileImageUrl:
timestamp:
username:
Wha should cause the crash?
Edit: I updated code like this which says that I have to :
Consider adding ".indexOn": "posts/username" at / to your security
rules for better performance
however I have pretty ok security rules:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"Snuses": {
".indexOn": ["Brand", "posts/username"]
}
}
}
FIRDatabase.database().reference().queryOrdered(byChild: "posts/username").queryEqual(toValue: currentUser.generalDetails.userName)
.observeSingleEvent(of: .value, with: { snapshot in
if ( snapshot.value is NSNull ) {
print("not found")
} else {
for child in (snapshot.children) {
let element = child as! FIRDataSnapshot //the node data
let key = element.key //the key for the node
let nodeToRemove = FIRDatabase.database().reference().child(key)
nodeToRemove.removeValue()
}
}
})
I believe you are going to want to remove child by it's parent key, not the child.
Frank provided a short comment (which is actually THE answer) but here's a verbose example (Firebase 2.x but you'll get the idea):
ref.queryOrdered(byChild: "posts/username").queryEqual(toValue: "someUsername")
.observeSingleEvent(of: .value, with: { snapshot in
if ( snapshot?.value is NSNull ) {
print("not found")
} else {
for child in (snapshot?.children)! {
let element = child as! FDataSnapshot //the node data
let key = element.key! //the key for the node
let nodeToRemove = ref.child(byAppendingPath: key)
nodeToRemove?.removeValue()
}
}
})
something to look for is to make sure your paths are correct.
In the above code, 'key' is the parent node name like
-KUaMd3YgJlQvv_P-kdK
If you were to use
let ref = element.ref
it would be the specific path to that node, including the node name but no other data, like this
root_node/posts/-KUaMd3YgJlQvv_P-kdK
so the idea is once you have that reference, use use the reference to remove the node.
So if ref = root_node/posts/-KUaMd3YgJlQvv_P-kdK
then ref.remove(), it will remove that reference and the child data.
Although #Jay's answer does your job, but i was half way through already writing your answer, Give it a shot and let me know:-
let refe = FIRDatabase.database().reference().child("posts")
refe.queryOrdered(byChild: "username").queryEqual(toValue: currentUser.generalDetails.userName).observeSingleEvent(of: .value, with: { (snapshot) in
if let snapDict = snapshot.value as? [String:AnyObject]{
for each in snapDict {
print(each.key)
refe.child(each.key).removeValue(completionBlock: { (err, ref) in
print(ref)
})
}
}
}, withCancel: {(errO) in
})
It should delete every posts that the user made.. :)

Swift, Firebase. Check if a users, childs value exists

In my game you, first have to login, then you have to choose a team name, which gets stored in my firebase database, under the players UID, and when the player has entered his team name, I want to check if it is already taken, or the player is good to go.
let rootRef = FIRDatabase.database().reference()
rootRef.queryOrderedByChild("teamName").queryEqualToValue("Bob fc").observeEventType(.Value, withBlock: { snapshot in
if (snapshot.value is NSNull) {
print("Name is not in use")
} else {
print("Name is in use")
}
})
My data tree:
{
"users" : {
"pbXvXYOKmJQqwSQZ9IlBykG7x1P2" : {
"teamName" : "Bob fc"
}
}
}
My database rules:
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
The problem is that it doesn't print anything, what am I doing wrong here?
You are querying your root ref. You should query the /users node instead
let rootRef = FIRDatabase.database().reference()
let usersRef = rootRef.childByAppendingPath("users")
usersRef.queryOrderedBy....
You can shorten that up but I used the verbose model for clarity.
As a side note, with Firebase 3.x, the default is to only allow authenticated users to read and write. This is accomplished through Rules in the Realtime Database section.
If you want to test your code without authenticating, change your Rules to this
{
"rules": {
".read": true,
".write": true
}
}
PLEASE NOTE: This opens up your data to ANYONE that wants to read it, but if you are just learning or testing an app it makes it a bit more convenient.