Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Firebase search in database

I search for users while typing. However at the end it returns every users. I don't know why exactly this happens. It seems alright

 class func findUsers(text: String)->[User]{
    let user = User()
    var users = [User]()
    ref.child("Users").queryOrderedByChild("name").queryStartingAtValue(text).observeEventType(.Value, withBlock: { snapshot in
        for u in snapshot.children{
            user.name = u.value!["name"] as? String
            user.surname = u.value!["surname"] as? String
            user.email = u.value!["email"] as? String
            user.score = u.value!["score"] as? Int
            user.status = u.value!["status"] as? Int
            user.id = u.value!["id"] as? String
            user.pin = u.value!["pin"] as? String
            users.append(user)
            print(user.name)
        }
    })
    print("users:", users)
    return users
}
like image 474
Robert Kim Avatar asked Jul 08 '16 20:07

Robert Kim


People also ask

Can you use firebase with Swift?

Use Swift Package Manager to install and manage Firebase dependencies. Visit our installation guide to learn about the different ways you can add Firebase SDKs to your Apple project, including importing frameworks directly and using CocoaPods. In Xcode, with your app project open, navigate to File > Add Packages.

What is uf8ff firebase?

The character \uf8ff used in the query is a very high code point in the Unicode range (it is a Private Usage Area [PUA] code). Because it is after most regular characters in Unicode, the query matches all values that start with queryText .


1 Answers

You are using queryStartingAtValue. From the documentation:

The FIRDatabaseQuery instance returned by queryStartingAtValue:childKey will respond to events at nodes with a value greater than startValue, or equal to startValue and with a key greater than or equal to childKey.

So keep in mind that if you search for the name of an user it will give all the users that have name greater in alphabetic order than the given one. You need to set a queryEndingAtValue to limit the query range.

ref.child("Users").queryOrderedByChild("name").queryStartingAtValue(text).queryEndingAtValue(text+"\u{f8ff}")

Firebase legacy documentation is such a good resource to understand on how firebase handle queries. There you will find:

The f8ff character used in the query above is a very high code point in the Unicode range. Because it is after most regular characters in Unicode, the query matches all values that start with a b.

You might also get interested in Elasticsearch. Flashlight is a node service that integrates elasticsearch and firebase.


Update:

As pointed out in the comments this won't work if the string you are searching for has upper case characters. The solution in this case is to have an additional field in the object with the info you are searching all in lower case. So if you have Satoshi Nakamoto as name you would save an additional nameSearch property with satoshi nakamoto.

And finally make sure your searching string is in lower case too.


There is a few other problems with your code.

  • You are setting an observer. It will trigger the callback anytime your data changes so you should be resetting the users array inside the callback so you don't have duplicated and dirty data.

  • Your function won't return the users with the data since firebase call is async. When you call return users you won't have the users array populated. I recommend you using self.users = users instead of returning it in the function. Otherwise, if you want to proceed with the current approach and return it, you should set a completion handler.


class func findUsers(text: String)->Void{
    ref.child("Users").queryOrderedByChild("name").queryStartingAtValue(text).queryEndingAtValue(text+"\u{f8ff}").observeEventType(.Value, withBlock: { snapshot in
        var user = User()
        var users = [User]()
        for u in snapshot.children{
            user.name = u.value!["name"] as? String
            ...
            users.append(user)
        }
        self.users = users
    })
}
like image 192
adolfosrs Avatar answered Oct 21 '22 21:10

adolfosrs