Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a paginated chronological query in Firestore

Hopefully a relatively simple question here with using Firestore querys

I am trying to create essentially a news feed, sorting the newest content from the oldest content. That part is pretty easy, I use:

var first = db.collection("feeds/0/active").orderBy("timestamp", "desc").limit(3);

Which retrieves the 3 newest entries in the news feed. My then idea is in the next query, to pull down the next 3 items in the feed. So if we are going by age, 4,5,6 in the collection in terms of how new the items are.

To do this I grab the last item in query one, and use that node's timestamp as my start at value in query 2:

  var first = db.collection("feeds/0/active").orderBy("timestamp", "desc").limit(3);

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


      var next = db.collection("feeds/0/active").orderBy("timestamp", "desc").startAt(lastVisible.data().timestamp).limit(3);
      next.get().then(function(docSn){
        console.log("SECOND QUERY!")
        docSn.forEach(function(doc) {
          console.log(doc.data().message)
        })
      })

The Result of this code returns the same as the first query returns, the nodes 1, 2, 3 despite trying to tell the second query to start at node3

I also tried passing in a javascript object instead:

  var datevalue = Date.parse(lastVisible.data().timestamp)    
  var next = db.collection("feeds/0/active").orderBy("timestamp", "desc").startAt(datevalue).limit(3);

Which also unfortunately did not work. I also tried passing in the entire snapshot item, and got the error "Malforormed Calls from JS: field sizes are different. [[9,38,38,38],[0,0,1,0], etc.."

Not really clue where to start with this as I have read through the docs and any examples and I could find and can't seem to figure it out. The only other way I can think of implementing this is by using a Cloud Function to number each node upon creation.. but that feels hacky

Any help would be huge! Thanks

like image 811
joe Avatar asked Oct 17 '17 02:10

joe


1 Answers

I have a collection called "books" with a field called "created" of type Timestamp. This is not a string. This is not a Date. Please see the Timestamp docs. You need to specify in your settings that you want to use the new Timestamp type instead of Date for your timestamp fields. (See docs for firestore settings)

Example of initiating your firestore and set the TimestampsInSnapshots setting:

   var firebaseApp = firebase.initializeApp({
        apiKey: [APIKEY],
        authDomain: [FIREBASEAPPDOMAIN],
        projectId: [PROJECTID]
   });

   var firestore = firebase.firestore();
   var settings = { timestampsInSnapshots: true }; // force Timestamp object instead of Date

   firestore.settings(settings);

When this is done, i've run the below code and I get the expected results. First query returns three results. Newest first, latest last. The second query returns the next three items.

var first = db.collection('books').orderBy("created", "desc").limit(3);
console.log("FIRST QUERY!")
first.get().then(function(documentSnapshots) {    
    documentSnapshots.forEach(function (doc) {
        console.log(doc.data().created.toMillis())
    });
    // Get the last visible document
    var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1];

    var next = db.collection('books').orderBy("created", "desc")
         .startAfter(lastVisible.data().created).limit(3);
    next.get().then(function (docSn) {
        console.log("SECOND QUERY!")
        docSn.forEach(function (doc) {
            console.log(doc.data().created.toMillis())
        });
    });
});

The console from the above code:

FIRST QUERY!
1540573716371
1540573676652
1540573668643

SECOND QUERY!
1540573658893
1540573536420
1540536647891
like image 191
ThdK Avatar answered Oct 20 '22 17:10

ThdK