How to get the last document from a VueFire query

firestore select fields
firebase realtime database pagination
firebase pagination swift
vuefire set

Getting frustrated to solve this since I am no JS expert. 😢

I am using Firestore as a database and VuexFire to bind the data to VueX state, like so.

 getLeads: firestoreAction(async ({
        bindFirestoreRef
    }) => {
        // return the promise returned by `bindFirestoreRef`
        return bindFirestoreRef('leads', db.collection('leads').orderBy('updated.date', 'desc').limit(30))
    }),

Lets say I have a collection of Customer records and i am displaying the first 5 ordered by last updated.

The query is

getLeads: firestoreAction(({ commit, bindFirestoreRef
}) => {
    bindFirestoreRef('Leads', db.collection('leads')
   .orderBy('updated.date', 'desc').limit(5)).then(documents => {
        commit('POPULATE_TESTLEADS', documents);
        commit('LAST_DOC', documents[documents.length - 1]);
    });

}),

I am saving both the results and the lastdoc in the state, looping and showing the names, like so:

Nakheel
Emaar Group
Yapi Kredi Inc
Cairo Amman Bank
Arab Jordan Investment Bank LLC

I then call again with the last doc as query cursor and expect the next 5 docs to return from firebase, like so

moreLeadLeads: firestoreAction(({ state, bindFirestoreRef
}) => {
    bindFirestoreRef('testLeads', db.collection('leads')
    .orderBy('updated.date', 'desc')
   .startAfter(state.lastDoc).limit(5))
}),

But I get the same 5 results as above from firestore. What am I doing wrong? :(

How to get the last document from a VueFire query – Onooks, In Firestore pagination require passing a query cursor of the last fetched document as a reference. Below from firebase document, with vanilla� Realtime bindings between Vue/Vuex and Firebase. Querying the database. So far we have used references to documents and collections and feed them to Vuefire to get a in-sync local version of them but you can also pass queries.

From the VueFire documentation on binding data and using it, the $bind method (which I assume your bindFirestoreRef wraps) returns a promise with the result (as well as binding it to this). From that documentation:

this.$bind('documents', documents.where('creator', '==', this.id)).then(documents => {
  // documents will point to the same property declared in data:
  // this.documents === documents
})

So you should be able to do the same, and then get the document from the array with something like:

bindFirestoreRef('leads', db.collection('leads').orderBy('updated.date', 'desc').limit(30)).then(documents => {
  this.lastDoc = documents[documents.length - 1];
})

Querying the database, So far we have used references to documents and collections and feed them to Vuefire to get a in-sync local version of them but you can also pass queries. Binds a collection, Query or Document to a property previously declared in the state, relatively to the module we are on. It unbinds any previouly bound reference with the same key . Returns a Promise that is resolved once the data has been completely fetched and synced into the state.

Internally VueFire and VuexFire use a serializer function that maps each Document returned by RTDB or Firestore into the data objects that are bound to the final component or Vuex store state.

The default serializer is implemented by the function createSnapshot that is part of the vuefire-core library:

/**
 * @param {firebase.firestore.DocumentSnapshot} doc
 * @return {DocumentData}
 */
export function createSnapshot (doc) {
  // defaults everything to false, so no need to set
  return Object.defineProperty(doc.data(), 'id', {
    value: doc.id
  })
}

As you can see it returns only doc.data() (with id added) and discards the doc object. However when implementing Firestore pagination via query.startAfter(doc) we need the original doc object. The good news is that VueFire and VuexFire APIs allow us to replace the serializer with our own that can preserve the doc object like so:

const serialize = (doc: firestore.DocumentSnapshot) => {
  const data = doc.data();
  Object.defineProperty(data, 'id', { value: doc.id });
  Object.defineProperty(data, '_doc', { value: doc });
  return data;
}

We can configure our new VuexFire serializer either globally via plugin options or per binding via binding options.

// Globally defined Vue.use(firestorePlugin, { serialize });

// OR per binding bindFirebaseRef('todos', db.ref('todos'), { serialize } )

For VuexFire, we can now get access to the first document as state.todos[0]._doc or last document state.todos[state.todos.length-1]._doc and use them to implement pagination queries for collections or "get next" & "get previous" queries that bind single documents (essential when your base query has multi-field sorting).

NOTE: Because _doc and id are non-enumerable properties, they won't appear on component or store objects in Vue DevTools.

Binding / Subscribing to changes, For Firestore, collections and queries are bound as arrays while documents are in db.doc('documents/robin-book') to get the actual reference to the document. To get last inserted document, use sort() along with limit(1).Let us first create a collection with documents −> db.getLastInsertedDocument.insertOne({Name:

Vuefire API Reference, import firebase from 'firebase/app' import 'firebase/firestore' // Get a Firestore Programatically binds a collection, document or query to an existing property� Vuefire Realtime bindings between Vue/Vuex and Firebase Get Started → Light. Both Vuefire and Vuexfire are under 2kb gzipped. Flexible.

Vuefire get document, Vuefire get document. You can query the service about many types of information, including Nov 20, 2018 � Then tell Vue to use the VueFire library. Sep 24 These arrays include multiple The issue is that the last document isn't a firesore� Installing Firebase and VueFire At this point, we have a blank Vue template that is ready for some magic from the cloud. Let’s open a Firebase account and start a new project on the free Spark

Fetching a single document causing onSnapshot function undefined , Just following the docs online for cloud firebase and trying to get a single onSnapshot is not a function at bindDocument (vuefire.esm.js?8676:575) at eval Just here in the official docs in the topic querying the database� Definition and Usage. The querySelector() method returns the first element that matches a specified CSS selector(s) in the document. Note: The querySelector() method only returns the first element that matches the specified selectors.

Comments
  • Thanks. But it deoesnt seem to work. Actually passing last document data to firestore cant be used as a query cursor. I should be passing a document reference, which is the parent of the document $bind returns :(
  • Can you show me the docs of the method that takes a document reference to initialize a cursor? In the clients that I regularly work with (JavaScript, ReactNative, Android, Swift, Flutter) it's a document snapshot as that contains the actual data that the cursor needs.
  • firebase.google.com/docs/firestore/query-data/query-cursors Its under Paginate a Query section
  • document snapshot is what the cursor needs, however, as in my original question, documents from $bind in VuexFire retunrs the actual data of the document and not the document snapshot.
  • You can also pass an array of values, instead of a document snapshot.
  • I am having the same issue. This almost got me there but I'm still unclear on how to get the paginated query results to bind to the original state data. I was not able to add a comment before so I created a new question here stackoverflow.com/questions/62639778/…
  • I've added some possible solutions for extending this to implement pagination. stackoverflow.com/a/62650214/365261