Back

How to read the most recent 25 documents, then the next 25 documents after?

  • 0
  • Databases
  • General
  • Web
Drake
16 Aug, 2023, 03:25

Please share your code

TL;DR
The user is asking for help on how to read the most recent 25 documents and then the next 25 documents after that. They initially tried sorting the documents in descending order but had trouble getting the next page. They were advised to use `cursorBefore` instead of `cursorAfter` and to pass in the newest document to fetch the older ones. The suggested solution is to sort the documents in descending order when listing them, fetch the 25 items, and then reverse the sorting on the frontend of the application. The user thanked the support and said they will try the solution later. No full code was shared.
kathelia.dokgu
16 Aug, 2023, 03:27
TypeScript
let filters = [
  Query.orderAsc('$createdAt'),
  Query.limit(25)
];

if (documents.length) {
  filters.push(Query.cursorAfter(documents[0].$id));
}

const response = await databases.listDocuments(
  Constants.APPWRITE_DATABASE_ID,
  Constants.APPWRITE_COLLECTION_ID,
  filters
);
Drake
16 Aug, 2023, 03:28

And then?

kathelia.dokgu
16 Aug, 2023, 03:30

Well this is how I fetch the documents. This was supposed to give me the most recent documents but it's giving me the oldest documents. I haven't really coded the part the fetches the next page.

Drake
16 Aug, 2023, 03:31

Order ascending created at gives you the oldest first. And you put cursor after the 1st document so it's going to return starting from the 2nd document

kathelia.dokgu
16 Aug, 2023, 03:32

So should I sort in descending order when listing the documents, get the 25 items, then on the frontend of my application, I reverse the sorting?

kathelia.dokgu
16 Aug, 2023, 03:32

I need the documents sorted in ascending order.

Drake
16 Aug, 2023, 03:33

Maybe use cursor before?

Drake
16 Aug, 2023, 03:34

But you'd need to pass in the newest document so that it will fetch the older ones

kathelia.dokgu
16 Aug, 2023, 05:04

This works for when I grab the documents in an ascending order - basically from oldest to newest:

TypeScript
const getDocuments = async () => {
  let queries = [
    Query.orderAsc('$createdAt'),
    Query.limit(25)
  ];

  if (documents.length) {
    queries.push(Query.cursorAfter(documents[documents.length - 1].$id));
  }

  const response = await databases.listDocuments(
    Constants.APPWRITE_DATABASE_ID,
    Constants.APPWRITE_COLLECTION_ID,
    queries
  );

  const documentsList = response.documents;

  setMessages((prevState) => [...prevState, ...documentsList]);
};

I just want to reverse this to get the most recent document first then to the oldest.

Drake
16 Aug, 2023, 05:34

To get the most recent document, you'll need to order by created at descending...

kathelia.dokgu
16 Aug, 2023, 05:38

Yes that is what I initially did. I sorted in descending order. But then I had problems getting the next page. I tried both cursor before and after and I don’t think it looks correct. I’ll take a look again tomorrow and see if I can explain it better. I’m no longer on my computer so I can’t show my current code.

joeyouss
16 Aug, 2023, 13:57

Hey, sure, let us know if it doesnt work and we can help debug

Drake
16 Aug, 2023, 16:11

you would sort descending just to get the last document. then you would use the cursorBefore(lastDocument.$id) without any ordering after

kathelia.dokgu
16 Aug, 2023, 21:21

Aaaah, I see what you mean. I'll try this out later after work. Thanks for the suggestion! I think that should fix my issue!

kathelia.dokgu
17 Aug, 2023, 03:29

I really can't get this to work. Let me try to illustrate what I'm trying to do. To scale it down a bit let's pretend I have 15 documents in my collection:

TypeScript
Doc 1
Doc 2
...
Doc 15

So if I want to get the 5 most recent documents first I would call listDocuments in descending order and a limit of 5. That would then give me:

TypeScript
Doc 15
Doc 14
Doc 13
Doc 12
Doc 11

When I display the results on my page, I do want the documents listed in ascending order:

TypeScript
Doc 11
Doc 12
Doc 13
Doc 14
Doc 15

When I scroll all the way up to the end of the container, I want to fetch the next most recent documents (documents 6-10 on the second request and documents 1-5 for the final request) and add the results to my component's state. This is the part where I'm unable to get it to work. If I use cursorBefore(lastDocument.$id), the cursor will be pointing to Doc 10 because my last document was Doc 11. And if I make another request for the next 5 documents, it will give me:

TypeScript
Doc 10
Doc 11
Doc 12
Doc 13
Doc 14
kathelia.dokgu
17 Aug, 2023, 03:32

If I use cursorAfter(lastDocument.$id), the cursor would be pointing to Doc 12 because my last document was Doc 11. And if I make another request for the next 5 documents, it will give me:

TypeScript
Doc 12
Doc 13
Doc 14
Doc 15
kathelia.dokgu
17 Aug, 2023, 03:34

The way I see it is that I need to set the cursor 5 documents before my last document (the number of documents I fetch in each batch) for this to work. So in my example, once I fetch Doc 15, 14, 13, 12 , and 11 - I would set my cursor all the way to 6 (11 minus 5) and then do another fetch which should give me Doc 6, 7, 8, 9, and 10.

Drake
17 Aug, 2023, 04:51

You're supposed to use cursor before and pass in doc 11 so that you'll get docs 5 - 10

kathelia.dokgu
17 Aug, 2023, 04:55

This is what I'm already doing and it gives me docs 10-14.

Drake
17 Aug, 2023, 04:56

You're passing in doc 15 and not doc 11

Drake
17 Aug, 2023, 04:56

Maybe share your full code

kathelia.dokgu
17 Aug, 2023, 05:03
TypeScript
const getDocuments = async () => {
  let queries = [Query.limit(Constants.DOCUMENTS_PER_BATCH)];

  if (documents.length) {
    // Subsequent fetches
    queries.push(Query.cursorBefore(documents[documents.length - 1].$id));
  } else {
    // First fetch
    queries.push(Query.orderDesc('$createdAt'));
  }

  const response = await databases.listDocuments(
    Constants.APPWRITE_DATABASE_ID,
    Constants.APPWRITE_COLLECTION_ID,
    queries
  );

  // Reverse on the first fetch because it's sorted in descending order
  const documentsList = messages.length ? response.documents : response.documents.reverse();

  // Add the new items at the start of the array since they are older documents
  setDocuments((prevState) => [...documentsList, ...prevState]);
};
kathelia.dokgu
17 Aug, 2023, 05:06

Looks like I need to use documents[0].$id instead of documents[documents.length - 1].$id since the oldest document is the first element on my array.

kathelia.dokgu
17 Aug, 2023, 05:11

I think that fixes my issue. Although as a feedback, this process doesn't feel intuitive in my mind. When the fetching is all in ascending order, it feels great, the experience was intuitive. But when fetching in reverse, not at all intuitive.

Regardless, thanks for your help as always!!

Reply

Reply to this thread by joining our Discord

Reply on Discord

Need support?

Join our Discord

Get community support by joining our Discord server.

Join Discord

Get premium support

Join Appwrite Pro and get email support from our team.

Learn more