2016-07-08 78 views
1

我是Firebase/swift新手,我試圖使用.indexOn對服務器上的一組節點進行排序。我搜索了SO和文檔以獲得編寫規則,但我正在努力使用索引的swift代碼的正確格式。Firebase&swift use.indexOn對數據快照進行排序

我的假設是,當我使用.indexOn規則時,返回的快照使用該索引來排序結果。通過在swift中使用.queryOrderedByChild(「title」),我否定了創建索引的服務器端性能優勢。如果這個假設不正確,請糾正我。

這裏是我的火力地堡DB結構的一個簡單的代碼片段:

{ 
    "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", 
     } 
     } 
    } 
    } 
} 

這裏是我的規則JSON:

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

這裏是我的SWIFT代碼:

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. 
} 

任何建議,我怎麼能修改我的Swift代碼來使用索引(或更正索引,如果這是錯誤的)會很好。

+0

我不完全清楚你的問題。添加索引後,您是否看到負面的性能影響?或者你的結果顯示不正常? –

+0

嗨@FrankvanPuffelen - 請記住我是一個新手,所以我有點困惑。我的結果目前按照它們存儲在Firebase中的順序顯示,未按索引排序。我在文檔中讀到,最好在服務器上使用.indexOn進行排序,因此決定先做這件事(我的數據集可能會變得相當大),因此我無法在此階段評論性能。 – James

+0

好吧,明白了。我會寫一個答案。對於未來的問題,最好只提一下出錯的部分。如果數組中的元素沒有按照您預期的順序排列,那麼使用索引時的性能影響是無關的 –

回答

2

您需要使用queryOrderedByChild當您請求數據並在您的規則中有一個關鍵字時。這裏是一個例子;

火力地堡單證

下面的例子演示瞭如何可以獲取由他們的明星排序的用戶的置頂帖的列表數:

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

該查詢將從路徑檢索用戶發表的帖子中該數據庫基於其用戶ID,按每個帖子收到的星星數量排序。這種使用ID作爲索引鍵的技術稱爲數據扇出。

對queryOrderedByChild方法的調用指定用於排序結果的子鍵。在這種情況下,帖子按每個帖子中「starCount」子項的值排序。有關如何排序其他數據類型的更多信息,請參閱查詢數據的排序方式。

請點擊鏈接瞭解更多詳情;

https://firebase.google.com/docs/database/ios/retrieve-data

+0

謝謝 - 我認爲我的困惑源於這樣一個事實,即我在文檔中看到,爲規則添加索引是個好主意。因此,我假定索引是*而不是使用.queryOrderedByChild()。由於@FrankVanPuffelen已經證實你的答案是正確的,我會按照你的建議繼續前進。非常感謝 – James

2

首先,你需要按照亞德的回答,並指定要在其中接收子節點的順序。單個列表可以有很多索引,您需要指定您想要的特定查詢的順序。

指定訂單後,Firebase數據庫會返回一個快照,其中包含與您的查詢匹配的節點以及這些節點在結果中的顯示順序信息。

但是字典沒有任何有關兒童順序的信息。所以,當你的代碼快照轉換成字典,有關訂單的所有信息丟失:

if let dictionaryOfMessages = snapshot.value as? [String: AnyObject] { 

出於這個原因,最好使用快照的內置方法用於遍歷子節點:

for child in snapshot.children { 
    let key = child.key as String 
    print(key) 
    messageArray.append(Message(json: JSON(child.value))) // JSON handling via SwiftyJSON 
    // set the messageId 
    messageArray[messageArray.count - 1].messageId = key 
} 
+0

感謝您確認Jad的答案和關於字典的提示。我仍不確定客戶端添加索引所帶來的性能優勢來自客戶如何在客戶到達後訂購結果,但我會繼續:-) – James

+1

客戶不訂購它們,它只是以正確的順序返回它們。一本字典是無序的,所以通過轉換成字典,你將所有的命令都扔掉了。 –

+0

@FrankvanPuffelen基於OP的代碼,如果我嘗試使用Swift庫(不使用REST API)讀取數據庫,是否還需要修改Firebase實時數據庫中的RULES,以便提高排隊性能? – bibscy