【问题标题】:Firestore + AngularFire2 pagination ( query items by range - .startAfter(lastVisible) )Firestore + AngularFire2 分页(按范围查询项目 - .startAfter(lastVisible) )
【发布时间】:2018-03-28 14:04:26
【问题描述】:

在一个组件中,我想从 FireStore 中提取一系列项目,例如。从 0 到 5,从 5 到 10 等等。我在 FireStore 的文档中找到了this,但他们不使用 AngularFire2,所以我更努力地尝试重构,因为我得到了更大的混乱。我通过简单的splice()'ing 使它工作:

service ->

topFirstScores(): AngularFirestoreCollection<Score> {
  return this.fireRef.collection('scores', r => r
          .orderBy('score', 'desc').limit(6)
  );
}

component ->

$scores = new Subject();

this.scores$ = this.$scores.asObservable();
if (this.scores === 'first') {
  this.scoreS.topFirstScores().valueChanges().take(1)
    .subscribe(_ => this.$scores.next(_.splice(0, 3)))
} else {
  this.scoreS.topFirstScores().valueChanges().take(1)
    .subscribe(_ => this.$scores.next(_.splice(3, 3)))
}

但这似乎更像是一种解决方法。谁能翻译一下:

var first = db.collection("cities")
        .orderBy("population")
        .limit(25);

return first.get().then(function (documentSnapshots) {
  // Get the last visible document
  var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
  console.log("last", lastVisible);

  // Construct a new query starting at this document,
  // get the next 25 cities.
  var next = db.collection("cities")
          .orderBy("population")
          .startAfter(lastVisible)
          .limit(25);
});

那最好返回AngularFirestoreCollection&lt;T&gt;?

【问题讨论】:

    标签: angular rxjs google-cloud-firestore angularfire2


    【解决方案1】:

    我遇到了同样的问题,这就是我所做的。

    服务

    private _data: BehaviorSubject<Scores[]>;
    public data: Observable<Scores[]>;
    latestEntry: any;
    
    constructor(private afs: AngularFirestore) {}
    
    // You need to return the doc to get the current cursor.
      getCollection(ref, queryFn?): Observable<any[]> {
        return this.afs.collection(ref, queryFn).snapshotChanges().map(actions => {
          return actions.map(a => {
            const data = a.payload.doc.data();
            const id = a.payload.doc.id;
            const doc = a.payload.doc;
            return { id, ...data, doc };
          });
        });
      }
    // In your first query you subscribe to the collection and save the latest entry
     first() {
      this._data = new BehaviorSubject([]);
      this.data = this._data.asObservable();
    
      const scoresRef = this.getCollection('scores', ref => ref
        .orderBy('score', 'desc')
        .limit(6))
        .subscribe(data => {
          this.latestEntry = data[data.length - 1].doc;
          this._data.next(data);
        });
      }
    
      next() {
        const scoresRef = this.getCollection('scores', ref => ref
          .orderBy('scores', 'desc')
           // Now you can use the latestEntry to query with startAfter
          .startAfter(this.latestEntry)
          .limit(6))
          .subscribe(data => {
            if (data.length) {
              // And save it again for more queries
              this.latestEntry = data[data.length - 1].doc;
              this._data.next(data);
            }
          });
      }
    

    组件

      scores$: Observable<Scores[]>;
      ...
      ngOnInit() {
        this.yourService.first();
        this.scores$ = this.yourService.data;
      }
    
      nextPage() {
       this.yourService.next();
      }
    

    【讨论】:

    • 如何获取之前的数据?
    • 您是否能够使之前的数据正常工作?我还在努力解决这个问题!
    • 这个解决方案不是真正的分页器。而是像 Facebook 或类似的无休止的滚动。
    【解决方案2】:

    源码教程Link

    AngularFire2 用于FireStore 数据库操作

    使用以下方法:

    下一页

        nextPage() {
          this.disable_next = true;
          this.firestore.collection('People', ref => ref
            .limit(5)
            .orderBy('timestamp', 'desc')
            .startAfter(this.lastInResponse)
          ).get()
            .subscribe(response => {
    
              if (!response.docs.length) {
                this.disable_next = true;
                return;
              }
    
              this.firstInResponse = response.docs[0];
    
              this.lastInResponse = response.docs[response.docs.length - 1];
              this.tableData = [];
              for (let item of response.docs) {
                this.tableData.push(item.data());
              }
    
              this.pagination_clicked_count++;
    
              this.push_prev_startAt(this.firstInResponse);
    
              this.disable_next = false;
            }, error => {
              this.disable_next = false;
            });
        }
    

    上一页

        prevPage() {
          this.disable_prev = true;
          this.firestore.collection('People', ref => ref
            .orderBy('timestamp', 'desc')
            .startAt(this.get_prev_startAt())
            .endBefore(this.firstInResponse)
            .limit(5)
          ).get()
            .subscribe(response => {
              this.firstInResponse = response.docs[0];
              this.lastInResponse = response.docs[response.docs.length - 1];
    
              this.tableData = [];
              for (let item of response.docs) {
                this.tableData.push(item.data());
              }
    
              //Maintaing page no.
              this.pagination_clicked_count--;
    
              //Pop not required value in array
              this.pop_prev_startAt(this.firstInResponse);
    
              //Enable buttons again
              this.disable_prev = false;
              this.disable_next = false;
            }, error => {
              this.disable_prev = false;
            });
        }
    

    this link查看完整的教程和演示

    【讨论】:

      【解决方案3】:

      我不了解 FireBase,但是当您询问所有项目然后进行过滤时,我很棒。

      如果您创建的方法具有参数、页面和大小以及数组 lastScore,我认为您可以创建一些类似的方法(注意:我没有 Firestone,而且很可能,我错了,代码很糟糕)

      //In service
      
      lastScores:number[]=[];
      lastPage:number=0; //use to know where you reach the last page
      getNextHightScores(page:number,count:number)
      {
          //get the limit
          let last=page>0?lastScores[page-1]:999999999   //if page=0 a bigger score
          //use where and limit
          return afs.collection<Item>('scores', r =>  
                  r.where("score", "<", last).orderBy("score","desc").limit(count)
                  .valueChanges()
                  .do(r=>{  //using do to store the lastScore
                     if (r.length)
                         this.lastScore[page]=r[r.length-1].score;
                     if (r.length<count)
                         this.lastPage=page;
                  })
      }
      
      //in component
      page:number=0;
      ngOnInit(){
          getValues(0);
      }
      
      getValues(page)
      {
          service.getNextHightScore(page,5).subscribe(r=>{console.log(r)})
      }
      //and 
      <button (click)="page=page+1;getValues(page)">next scores</button>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-15
        • 2018-04-10
        • 2019-11-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多