Search code examples
javascriptangularfirebasegoogle-cloud-firestoreangularfire2

How to query firestore w.r.t realtime?


So there is a list of notification objects stored in notifications collection and my goal is to retrieve all notifications which are older than current date-time.

So my basic query was:

    return this.db.collection(environment.collection, ref => ref.where('staffRole', '==', staffRole).where('notificationDate', '<=', new Date().getTime()).orderBy('notificationDate', 'desc'))
      .snapshotChanges()
      .pipe(map(snaps => {
        return snaps.map(snap => {
          return <Notification>{
            id: snap.payload.doc.id,
            ...Object.assign({}, snap.payload.doc.data())
          }
        });
      }));

But new Date().getTime() is passed as fixed-parameter and not realtime as I expected. To overcome this, I altered the subscribing part:

interval(1000)
  .pipe(
    map(tick => new Date()),
    share()
  ).subscribe(date => {
    // console.log(date.getTime());
    this.notificationSubscriber !== undefined ? this.notificationSubscriber.unsubscribe() : false;
    this.notificationSubscriber = this.notificationService.getNotifications(getStaffRolevalue(this.staffRole),
      (this.staffRole === 'csa' || 'ops' || 'admin' ? null : this.loggedInStaffId)).subscribe(notifications => {
        this.notifications = notifications;
        const x = this.notificationCount;
        this.notificationCount = notifications.filter(notification => notification.isRead === 0).length;
        const y = this.notificationCount;
        (y - x) === 1? this.playAudio() : false;
      });
  });

My logic was to resubscribe to the observable every second. It did work but the database usage for reading documents skyrocketed. So basically this logic cannot be used as well.

Is there any other way to achieve what I'm trying to. I'm open to any suggestions even if it is about changing my interface as long as I retrieve notifications with respect to realtime.

Interface:

export interface Notification {
    id: string,
    isRead: number,
    jobNo: number,
    notificationDate: number,
    notificationMessage: string,
    notificationTitle: string,
    notificationType: number,
    receiverId: string,
    staffRole: number
}

Solution

  • I changed my query in service to a simple query:

            return this.db.collection(environment.collection, ref => ref.where('receiverId', '==', staffId))
              .snapshotChanges()
              .pipe(map(snaps => {
                return snaps.map(snap => {
                  return <Notification>{
                    id: snap.payload.doc.id,
                    ...Object.assign({}, snap.payload.doc.data())
                  }
                });
              }));
    

    And applied all my logic while I was subscribing:

        this.notificationService.getNotifications(getStaffRolevalue(this.staffRole),
          (this.staffRole === 'csa' || 'ops' || 'admin' ? null : this.loggedInStaffId)).subscribe(notifications => {
            this.timer !== undefined ? this.timer.unsubscribe() : false;
            this.timer = interval(5000)
              .pipe(
                map(tick => new Date()),
                share()
              ).subscribe(date => {
                this.notifications = notifications.filter(notification => notification.notificationDate <= date.getTime()).sort(function (a, b) { return b.notificationDate - a.notificationDate });
                const x = this.notificationCount;
                this.notificationCount = this.notifications.filter(notification => notification.isRead === 0).length;
                const y = this.notificationCount;
                y - x === 1 ? this.playAudio() : false;
              });
          });