2014-04-24 42 views
1

我正在使用Firebase構建排行榜。使用Firebase的優先系統跟蹤玩家在排行榜中的位置。獲取Firebase中有序列表中對象的索引

在我的程序執行過程中,我需要知道給定用戶在排行榜中的位置。我可能有成千上萬的用戶,因此遍歷所有這些用戶以找到具有相同ID的對象(因此給我索引)並不是真正的選擇。

是否有更高性能的方式來確定Firebase中有序列表中對象的索引?

編輯:我想弄清楚以下幾點:

/ 
---- leaderboard 
--------user4 {...} 
--------user1 {...} 
--------user3 {...} <- what is the index of user3, given a snapshot of user3? 
--------... 
+0

你有沒有數據結構的例子?你看過[排行榜榜樣](http://stackoverflow.com/questions/23259046/getting-the-index-of-an-object-in-an-ordered-list-in-firebase),它的數據架構? – Kato

+0

剛剛添加了我的數據結構的一個例子。假設我擁有的是UID('user3')和/或'user3'節點的快照。我如何知道它在'排行榜'(它被用作一個有序列表)中的位置/索引?是的,我確實看過排行榜的例子。不幸的是,它不會在排行榜中列出子節點的索引。 –

回答

6

如果您需要處理幾十或幾百元的,不介意的帶寬命中,看到Kato的回答。

如果你正在處理的記錄thounsands,你需要按照pperrin的回答原則概括的方法。以下答案詳細說明。

第1步:安裝手電筒指數的排行榜與ElasticSearch

手電筒是一個方便的節點腳本與火力地堡數據同步elasticsearch。

Read about how to set it up here.

第2步:修改手電筒,讓您可以通過查詢選項來ElasticSearch

截至記者發稿,手電筒讓你沒有辦法告訴ElasticSearch你只在感興趣的文件匹配,並且不是的文件本身。

I've submitted this pull request它使用簡單的一行修補程序來添加此功能。如果在閱讀此答案時未關閉,只需手動更改手電筒的副本/分叉即可。

第3步:執行查詢!

這是我通過火力地堡發送的查詢:

{ 
    index: 'firebase', 
    type: 'allTime', 
    query: { 
     "filtered": { 
      "query": { 
       "match_all": {} 
      }, 
      "filter": { 
       "range": { 
        "points": { 
         "gte": minPoints 
        } 
       } 
      } 
     } 
    }, 
    options: { 
     "search_type": "count" 
    } 
}; 

更換points與用戶現場跟蹤點的名稱,並minPoints與它的排名,你有興趣的用戶的點數。

響應看起來像:

{ 
    max_score: 0, 
    total: 2 
} 

total是NUM具有相同或更多點數的用戶 - 換句話說,用戶的排名!

+1

很棒的工作Dany!很有創意。我也合併了公關。 – Kato

1

由於火力地堡存儲對象,不是數組的元素沒有在列表中的「指標」 - JavaScript和通過擴展JSON對象本質上是無序的。如Ordered Docs中所述,並在leaderboard example中演示,您可以使用優先級完成排序。

一組操作:

var ref = new Firebase('URL/leaderboard'); 
ref.child('user1').setPriority(newPosition /*score?*/); 

讀操作:

var ref = new Firebase('URL/leaderboard'); 
ref.child('user1').once('value', function(snap) { 
    console.log('user1 is at position', snap.getPriority()); 
}); 
+0

與firebase上的排行榜示例類似,我使用分數來設置優先級,而不是位置。例如,'user1'可能具有500的優先權,其中'user3'可能具有1000的優先權。當然,'user1'或'user3'分別不佔用第500和第1000個位置。您如何推薦我重組我的數據,以便在這種情況下我可以獲得節點的位置? –

+0

沒有立場。這是一個對象(即鍵是無序的)。如果你認真思考,你會發現「位置」實際上是一個隨着記錄被添加,刪除和重新定位而不斷變化的任意數字。每次有變化時,您都需要重新計算(或將項目放入數組並讀取索引;像Angular這樣的工具可以幫助您) – Kato

+0

感謝加藤。我一直都知道,「排行榜」實際上是一個對象,我只是問你是否可以想出一種方法來構造FB中的數據,從而使對象位置變得微不足道。無論哪種方式,我很好奇Angular如何能夠提供幫助?我正在使用Backbone。我想不出有什麼更好的辦法,但是每次我需要知道特定對象的等級時,要迭代1000多個元素。 –

1

爲了得到你想要的信息,在某個時間點的過程將不得不枚舉節點指望他們。那麼問題出在哪裏/何時發生。

使用.Count之間的()在客戶端將意味着它每做它是需要時間的,這將是相當準確的,但處理。第/交通重工。

如果保持計數的獨立指數將需要定期清爽,或不斷更新(每個刀片causeing一個洗牌餘下的條目)。

根據數據的分佈和數量我會受到誘惑與剛剛更新(/重建)後臺進程去每一個(說)一二十添加索引。並索引每個(說)10個職位。

"Leaderboard",$UserId = priority=$score 
... 

"Rank",'10' = $UserId,priority=$score 
"Rank",'20' = $UserId,priority=$score 
... 

從你得到10內的排名,然後用startat/EnDat數據的得分/指望你的「排行榜」它弄下來到單位。

如果你的後臺進程正在監視更新到排行榜,也可能是有關其更新的索引或者只更新爲requried更多inteligent。

+0

嘿pperrin!偉大的信息和偉大的見解。我昨天意識到同樣的事情;唯一的細微差別是我現在使用elasticsearch來進行等級索引。每次請求排名(並且迭代都不是選項)時,我通過firebase發送一個查詢到彈性搜索來計算索引中元素的數量,其'totalPoints'大於發送ID的元素。該數字,加一,就是排名。一旦完成我的實施,我會發布後續答案。 –

+0

我已經添加了類似於您使用ElasticSearch描述的內容的實現。 –