2017-07-25 30 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所示。

所以您的查询就会是这个样子:

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

请注意,我用toFirst: 3+1。这是因为,恼人的是,startAt()是包容性的,没有办法跳过第一条记录。因此,由于我们从上一页上的最后一条记录开始,您将需要查询一条额外的记录并放弃第一条结果。

下面是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; 
    }); 
    } 
} 

and here's a working fiddle

请记住,这是一个实时数据流。所以分页是棘手的。做一个无限滚动通常比在一个移动的数据集上尝试和维护一个真实的光标更容易(记录可以在数据改变,被删除,添加在中间等时重新排序)。

+0

看起来像它的工作原理,但无论如何,你可以在swift中发布解决方案吗? – Dirty

+0

答案是在您的startAt()调用中使用childKey。剩下的只是奖金,可以帮助您了解下一步将要走向何方。 – Kato

+0

谢谢!答案接受! – Dirty

相关问题