Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep the order of list in sql pagination

I have a list with an order of insertion. I want to paginate the results using the same order. As you can see currently the output will be a different order.

following_companies_list_data = Company.query.filter(Company.id.in_(['2', '24', '1', '7', '373'])).paginate(
            page, per_page=10, error_out=False)

companies = following_companies_list_data.items

for i in companies:
    print i.id

7
24
373
2
1

related question

like image 789
user455318 Avatar asked Feb 12 '16 00:02

user455318


People also ask

What is offset in pagination?

The OFFSET clause specifies the number of rows of the result table to skip before any rows are retrieved, and must be used with the LIMIT clause. The OFFSET clause instructs the server where to start returning rows within the query result.

What is keyset pagination?

Keyset pagination (also known as the "seek method") is used to fetch a subset of records from a table quickly. It does this by restricting the set of records returned with a combination of WHERE and LIMIT clauses.

Will pagination improve performance?

Thanks to pagination, we can split our large dataset into chunks ( or pages ) that we can gradually fetch and display to the user, thus reducing the load on the database. Pagination also solves a lot of performance issues both on the client and server-side!


2 Answers

Solution based on this answer from related question

company_ids = ['2', '24', '1', '7', '373']
order_expressions = [(Company.id==i).desc() for i in company_ids]
query = Company.query.filter(Company.id.in_(company_ids)).order_by(*order_expressions)
following_companies_list_data = query.paginate(page, per_page=10, error_out=False)

Also you can use idx function from intarray module

from sqlalchemy import func
company_ids = ['2', '24', '1', '7', '373']
query = Company.query.filter(Company.id.in_(company_ids)).order_by(func.idx(company_ids, Company.id))
following_companies_list_data = query.paginate(page, per_page=10, error_out=False)
like image 66
r-m-n Avatar answered Oct 05 '22 10:10

r-m-n


I think the easiest way to do this is to paginate your list of IDs before even querying:

company_ids_page = company_ids[page * 10:(page + 1) * 10]
q = Company.query.filter(Company.id.in_(company_ids_page))

Then, reorder companies based on the order of your ids:

companies_map = {c.id: c for c in q}
companies = [companies_map[i] for i in company_ids_page]

If you need the fancy features of Pagination objects you can probably create a similar class for lists.

like image 37
univerio Avatar answered Oct 05 '22 08:10

univerio