implementing firestore onsnapshotListner feature with pagination

I have a web application that needs real-time updates on a large collection of documents. However, due to the size of the collection, retrieving data without applying a limit is not feasible and inefficient. Therefore, it is crucial to implement a query limit. Currently, I am fetching data in chunks of 50. I came across the reference Firestore reactive pagination, which has been working well for me.

One confusion I have regarding the code below is how document reads are calculated. The code first retrieves documents using the normal get() method in chunks of 50 and then attaches a listener to the response from the get() method. Will Firestore count an additional 50 reads or just 50?

Below is the code snippet of what I have implemented:


var messages = [] 
var listeners = []    // list of listeners
var start = null      // start position of listener
var end = null        // end position of listener

function getMessages(chatId) {

// query reference for the messages we want

let ref = db.collection('chats').doc(chatId)
.collection('messages')

// single query to get startAt snapshot

ref.orderBy('createdAt', 'desc')
.limit(50).get()
.then((snapshots) => {

// save startAt snapshot

start = snapshots.docs[snapshots.docs.length - 1]

// create listener using startAt snapshot (starting boundary)

let listener = ref.orderBy('createdAt')
  .startAt(start)
  .onSnapshot((messages) => {
    // append new messages to message array
    messages.forEach((message) => {
      // filter out any duplicates (from modify/delete events)         
      messages = messages.filter(x => x.id !== message.id)
      messages.push(message.data())
    })
  })

  // add listener to list

  listeners.push(listener)
})
}

 function getMoreMessages(chatId) {

let ref = db.collection('chats').doc(chatId)
.collection('messages')

// single query to get new startAt snapshot

ref.orderBy('createdAt', 'desc')
.startAt(start)
.limit(50).get()
.then((snapshots) => {

 // previous starting boundary becomes new ending boundary

  end = start
  start = snapshots.docs[snapshots.docs.length - 1]

  // create another listener using new boundaries     

  let listener = ref.orderBy('createdAt')
  .startAt(start).endBefore(end)
  .onSnapshot((messages) => {
    messages.forEach((message) => {
      messages = messages.filter(x => x.id !== message.id)
      messages.push(message.data())
    })
  })
  listeners.push(listener)
})
}

// call to detach all listeners
function detachListeners() {
 listeners.forEach(listener => listener())
 }

Answer №1

Executing the following query will consume 50 document reads:

ref.orderBy('createdAt', 'desc').limit(50).get()

Subsequently, running this query will also incur at least the same number of document reads:

ref.orderBy('createdAt').startAt(start).endBefore(end).onSnapshot(...)

It is possible that even more document reads will be consumed depending on how frequently those documents are updated while the listener is active.

Firestore does not provide a straightforward mechanism for combining real-time updates with pagination. Creating custom solutions like this one can be quite resource-intensive.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Gatsby website failing to create slugs as anticipated

While trying to follow the Gatsby tutorial, I ran into an issue with generating slugs for MDX files in a subdirectory of src/pages. For instance, if I have a file like src/pages/projects/devmarks/index.md, the expected slug according to the tutorial should ...

What is the process for deconstructing errors from the RTK Query Mutation Hook?

Currently, I am utilizing redux toolkit query for handling my data fetching API. One issue that I have encountered is with error handling. When an error is returned from the server, it comes in as an object with nested data. However, when trying to access ...

What issues can trailing white space cause in TypeScript coding?

While I understand that linting is the reason for this, why are trailing spaces considered problematic? I plan to disable this feature in tslint.json, but before I make that change, I want to ensure I'm not making a mistake. Visual Studio Code alert ...

Retrieve the value of a variable to access an object property dynamically in React Native using TypeScript

As I attempted to create dynamic styles for this component, my goal was to determine the styles based on a string passed in as a property. Here is the code snippet: export type MyComponentProps = { styleName: string; } const MyComponent = (props: MyComp ...

How to toggle CSS class in Angular2/Typescript to mimic radio buttons behavior

Is there a way to create a radio button group using UL and LI elements in Angular2 and Typescript? The goal is to have all the anchors function like a radio button group where only one can be selected at a time. The selected anchor should remain "clicked" ...

Exploring Typescript's type narrowing capabilities through destructuring

This code snippet is encountering errors: type Example = { x: true, y: null, z: null } | { x: false, y: Error, z: null } | { x: false, y: null, z: { val: number} } function getExample(): Example { return { x: false, y: null, z: { val ...

What is the best way to incorporate the TUI image editor for Javascript into my Angular application?

Issue - I'm facing a challenge with my Angular application as I want to integrate Toast UI image editor. However, I am unsure about how to properly add the imports to app.module.ts in order to utilize it. Despite following the npm installation instru ...

What is causing the issue with TypeScript's React.createRef() and its compatibility with the material-ui Button element?

Running on React version 16.13.1, my component class includes a Material-UI Button component and a RefObject to access the button element. class Search extends React.Component<any, any>{ constructor(props: any) { super(props) this.streetV ...

Generating a date without including the time

I recently started working with React (Typescript) and I am trying to display a date from the database without including the time. Here is my Interface: interface Games { g_Id: number; g_Title: string; g_Genre: string; g_Plattform: string; g_ReleaseDate: ...

Tips for displaying validation error messages in an Angular form

I need help displaying a validation error message for an Angular form. I have three checkboxes and I want to show an error message if none of them are selected. Can anyone provide guidance on how to implement reactive form validation in Angular? Here is a ...

Conceal the HTML element within a subscription

Currently, I am utilizing Angular and have a checkbox that I need to toggle visibility based on the response of an API call subscription. The issue lies in a delay when trying to hide the checkbox (as it is initially set to visible). My assumption is that ...

Unable to integrate the leaflet-realtime plugin with Angular5 and Ionic at this time

Having trouble utilizing the leaflet-realtime plugin in my Ionic3 & Angular 5 project When I import import leaflet from 'leaflet'; in this manner Upon attempting to implement real-time functionality with the following code snippet leaflet ...

Is it possible to locate a Typescript class only when there are no references to its properties?

Currently, I am utilizing TypeScript 2.0 within VSCode and although the highlighted errors are being confirmed by the TypeScript compiler, they all point to a module that I am importing: import * as els from 'elasticsearch'; The module elastics ...

Experimenting with Typescript, conducting API call tests within Redux actions, mimicking classes with Enzyme, and using Jest

I am facing an issue where I need to mock a class called Api that is utilized within my redux actions. This class is responsible for making axios get and post requests which also need to be mocked. Despite following tutorials on how to mock axios and class ...

Error in Typescript SPFx: The property 'news' is not found in the type 'Readonly<{}>'

Currently, I am working on developing a spfx react component to showcase an RSS feed in the browser. My prototype is functional in a test environment, however, as spfx utilizes TypeScript, I am encountering a type error that I am unsure how to resolve. Rs ...

Tips for storing the device token received from Firebase Cloud Messaging in an Ionic2 application

Using the FCM plugin for ionic2, I was able to successfully implement push notifications. For reference, you can check out the plugin here. I followed the steps outlined in this Github repository, and everything is working smoothly so far. Now, my next go ...

Manipulating a <DIV> style within an Angular 8 project

Looking to change the display style? Check out this template: <div style="display: none" #myDiv /> There are 2 methods to achieve this: Method 1: Directly if (1===1) this.myDiv.style.display = "block"; Method 2: Using @ViewChild @ViewChild(&apo ...

Issue with decompressing the identical data using zlib (Z_BUF_ERROR)

Below is the Python code snippet I am working with: import zlib raw = bytes.fromhex("789C34C9410AC2301005D0BBFC752289A88BB94A53CAD8061B48D3329D2A1A7277DDB87BF02A14548E9C0DF63FD60DE49DC104AA98238BDE23EB908A467972065DFCF9FAFB4185C708EAD0053C58E38BDF769 ...

Having trouble implementing object type switching in Typescript

While in the process of developing an angular application, I stumbled upon a peculiar issue. Some time ago, I crafted this piece of code which performed flawlessly: selectedGeoArea: any receiveStoreEvent(event) { switch (event.constructor) { ca ...

Preventing Bootstrap modal from closing when clicking outside of the modal in Angular 4

I'm working with Angular 4 and trying to prevent the model from closing when I click outside of it. Below is the code snippet I am using: <div id="confirmTaskDelete" class="modal fade" [config]=" {backdrop: 'static', keyboard: false}" ro ...