Firestore + AngularFire2 pagination ( query items by range - .startAfter(lastVisible) )

后端 未结 3 437
借酒劲吻你
借酒劲吻你 2020-12-09 13:56

In a component I want to pull a range of items from FireStore, for ex. from 0 to 5, from 5 to 10 etc. I found this in FireStore\'s docs, but they dont use AngularFire2 so as

相关标签:
3条回答
  • 2020-12-09 14:09

    Source Tutorial Link

    AngularFire2 used for FireStore database operations

    using below methods:

    For Next Page

        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;
            });
        }
    

    For Previous Page

        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;
            });
        }
    

    Check complete tutorial and demo on this link

    0 讨论(0)
  • 2020-12-09 14:12

    I don't know about FireBase, but I'am awesome when you ask about all the items and then filtered.

    If you make a method that has as arguments, page and size and an array lastScore I supouse that you can make some like (NOTE: I have NOT Firestone and, the most probably, I'm wrong and the code is bad)

    //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>
    
    0 讨论(0)
  • 2020-12-09 14:19

    I had the same Problem and this is what i did.

    Service

    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);
            }
          });
      }
    

    Component

      scores$: Observable<Scores[]>;
      ...
      ngOnInit() {
        this.yourService.first();
        this.scores$ = this.yourService.data;
      }
    
      nextPage() {
       this.yourService.next();
      }
    
    0 讨论(0)
提交回复
热议问题