2017-07-25 5 views
0

私のデータ構造がある値:ページネーションは、次のように

users: 
    user1: 
    -carModel: evo x 
    -username: importguy 
    -region: north east 
    user2: 
    -carModel: evo x 
    -username: evoguy 
    -region: north east 
    user3: 
    -carModel: mustang gt 
    -username: muscleguy 
    -region: south east 

私は、ユーザーが車を検索することができるようにしたい、それらの特定の車を所有するユーザーのEVO、表示結果を言います。私は私のアプリのためにこれらの結果を改ページする必要があります。問題は、これを適切に照会する方法を理解できないことです。ここに私がこれまで持っていたものがあります。

func fetchUsersBy(car: String) { 

    if self.carCurrentKey == nil { 

     let ref = USER_REF.queryOrdered(byChild: "carModel").queryStarting(atValue: car).queryLimited(toFirst: 3) 

     ref.observeSingleEvent(of: .value, with: { (snapshot) in 

      guard let snap = snapshot.children.allObjects as? [FIRDataSnapshot] else { return } 
      guard let last = snapshot.children.allObjects.last as? FIRDataSnapshot else { return } 

      snap.forEach({ (snapshot) in 

       guard let userDict = snapshot.value as? Dictionary<String, AnyObject> else { return } 
       guard let carModel = userDict["carModel"] as? String else { return } 

       if carModel.contains(car) { 
        print(snapshot) 
       } 
      }) 
      self.carCurrentKey = last.key 
      self.carCurrentValue = last.childSnapshot(forPath: "carModel").value as? String 
     }) 
    } else { 
     // where to start next query? 
     let ref = USER_REF.queryOrder(byChild: "carModel").queryStarting(atValue: self.carCurrentValue) 
    } 
} 

私はスナップショットにその特定の車種を持つすべてのユーザーをグループ化するためには、carModelでクエリを注文する必要があります。すべての車種モデルが同じ値なので、ページネーションの次のクエリをどこで開始するか終了させるかはわかりません。 elseブロックにある参照を使用すると、上記のブロックと同じ場所でクエリが開始されます。どんな助けやアドバイスも大歓迎です。

私はファンアウトを行い、車種別の構造を作ることを検討しました。しかし、これは難しいだろう。

答えて

1

startAt()とendAt()の両方で、childKeyのように、hereのように2番目の値を渡すことができます。私はtoFirst: 3+1を使用

let ref = USER_REF.queryOrdered(byChild: "carModel").queryStarting(atValue: self.carCurrentValue, childKey: self.carCurrentKey).queryLimited(toFirst: 3+1) 

注:

だからあなたのクエリは次のようになります。これは、annoyingly startAt()がインクルーシブなので、最初のレコードをスキップする方法がないからです。したがって、前のページで取得した最後のレコードから開始したので、1つの余分なレコードを照会して最初の結果を破棄したいと思うでしょう。

JavaScriptでさらに完全な例があります。これをSwiftに変換するのには慣れていませんが、完了時にアルゴリズムが必要です。

class Cursor { 
    constructor(baseRef, pageSize) { 
     this.baseRef = baseRef; 
     this.lastKey = null; 
     this.lastValue = null; 
     this.pageSize = pageSize; 
    } 

    next() { 
    let ref = this.baseRef; 

    if(this.lastValue !== null) { 
     // a previous page has been loaded so get the next one using the previous value/key 
     // we have to start from the current cursor so add one to page size 
     ref = ref.startAt(this.lastValue, this.lastKey).limitToFirst(this.pageSize+1); 
    } 
    else { 
     // this is the first page 
     ref = ref.limitToFirst(this.pageSize); 
    } 

    return ref.once('value').then(snap => { 
     const keys = []; 
     const data = []; // store data in array so it's ordered 

     snap.forEach(ss => { 
      data.push(ss.val()); 
      keys.push(ss.key); 
     }); 

     if(this.lastValue !== null) { 
     // skip the first value, which is actually the cursor 
     keys.shift(); 
     data.shift(); 
     } 

     // store the last loaded record 
     if(data.length) { 
     const last = data.length - 1; 
     this.lastKey = keys[last]; 
     this.lastValue = data[last].author; 
     } 

     return data; 
    }); 
    } 
} 

およびhere's a working fiddle

これはリアルタイムのデータストリームであることに注意してください。だから、改ページは難しいです。移動するデータセット上で現実的なカーソルを維持しようとするよりも、無限のスクロールを行う方が一般的に簡単です(データの変更、削除、途中での追加など)。

+0

はうまくいくようですが、とにかく迅速に解決策を投稿できますか? – Dirty

+0

答えは、startAt()の呼び出しでchildKeyを使用することです。残りは、あなたが次に向かうところを見るのを助けるための単なるボーナスです。 – Kato

+0

ありがとうございます!答えが受け入れられました! – Dirty