James James - 3 months ago 36x
Swift Question

Firebase & swift use .indexOn to sort data snapshot

I'm a Firebase/swift newbie and I'm trying to use .indexOn to sort a set of nodes on the server. I've searched SO and the docs to get the rules written but I'm struggling with the correct format for the swift code to use the index.

My assumption is that when I use an .indexOn rule the returned snapshot uses that index to order the result. By using .queryOrderedByChild("title") in swift I negate the server-side performance benefits of creating the index. Please correct me if this assumption is incorrect.

Here's a simplified snippet of my Firebase DB structure:

"users": {
"GkdjgdBJh1TxuAzIPezLWRouG9f2": {
"messages": {
"-KM0crettRl-RLQQdmMQ": {
"body": "Anyone want a bit of body string?",
"title": "5 Another title string",
"-KM0dhkChY6ZQ2QzuPlC": {
"body": "This is a short body string",
"title": "1 A lovely title string",
"-FQ0dhkChY6ZQ2Qzu3RQv": {
"body": "Short and sweet body string",
"title": "3 I should be in the middle",

Here's my rule JSON:

"rules": {
".read": true,
".write": true,
"users": {
"$userid": {
"messages": {
".indexOn": ["title"]

Here's my swift code:

if let user = FIRAuth.auth()?.currentUser {
// user is logged in

// *** I think this is the line with the issue ***
FIRDatabase.database().reference().child("users").child(user.uid).child("messages").observeEventType(.Value, withBlock: { (snapshot) in
messageArray = []

if let dictionaryOfMessages = snapshot.value as? [String: AnyObject] {
for messageKey in dictionaryOfMessages.keys {
messageArray.append(Message(json: JSON(dictionaryOfMessages[messageKey]!)))
// set the messageId
messageArray[messageArray.count - 1].messageId = messageKey
// return the data to the VC that called the function
success(messages: messageArray)
}) { (error) in
// Handle the Error
} else {
// return some generic messages about logging in etc.

Any suggestions how I can modify my Swift code to use the index (or correct the index if that's wrong) would be great.

Jad Jad

You need to use queryOrderedByChild when you're requesting the data and have a key in your rules as you did. here's an example;

Firebase documentations

The following example demonstrates how you could retrieve a list of a user's top posts sorted by their star count:

// My top posts by number of stars
let myTopPostsQuery = (ref.child("user-posts").child(getUid())).queryOrderedByChild("starCount")

This query retrieves the user's posts from the path in the database based on their user ID, ordered by the number of stars each post has received. This technique of using IDs as index keys is called data fan out.

The call to the queryOrderedByChild method specifies the child key to order the results by. In this case, posts are sorted by the value of the "starCount" child in each post. For more information on how other data types are ordered, see How query data is ordered.

Please follow the link for more details;