Hi, I have a big list in my GenServer
which I want to load them as a pagination, for example I counted it and I have x records and I want to load it with a page size (like 20).
my user inputs: page 1
and this pagination should load (1 - 20) records and if my user inputs page 2
, it should loads (21 - 40).
I saw Stream.resource
but I couldn’t use it
Please help me to understand this!!
Thanks
Not sure if this would be the best way
Stream.chunk_every(list_of_items, 20)
|> Enum.at(page - 1)
2 Likes
In BEAM lists are “linked” lists… so any page > 1 would require somehow to traverse the list… Either if you skip first N and take M elements… or if you “chunk_every” M and take Nth chunk of it.
We need some sort an indexing… What about storing in a map where key is the index? Then based on the request you quickly figure out the required keys and do Map.take/2
?
Or maybe store somewhere that supports pagination? :ets and :mnesia support match specs… But to rephrase a regex joke “if you decide to use a match spec you now have two problems”
Depends on the task =)
1 Like
If your elements are in memory, then you can just do:
page_size = 10
page_num = 3
list_of_elements
|> Enum.drop(page_size * (page_num - 1))
|> Enum.take(page_size)
This will give you the elements on the 3rd page (21 through 30).
However, keeping a large list in memory and implementing pagination in this way is potentially inefficient.
May ask you where your data is loaded from? It may be more efficient to offload pagination to the data source. For example, if the data source is an SQL database, you could fetch the elements for a given page with:
SELECT * FROM DATA
ORDER BY <SOMETHING>
OFFSET page_size * (page_num - 1)
LIMIT page_size
In this way only the elements of the desired page will be loaded every time, and with the proper indexes set up in your DB the query will be fast.
1 Like
Hi! This is a very useful library:
1 Like