-
Notifications
You must be signed in to change notification settings - Fork 21
Description
What
- The
order_byargument should accept not only field names, but also sql statements, e.g.CONCAT(field, otherfield)orFIELD(field, 'value1', 'value2') - The
order_byvalue, which defaults toid, should be used as the cursor, for filtering and for ordering - All custom ordering logic should be removed from the gem
- Update readme, to specify that the
order_bycolumn is expected to be a unique and should be indexed, and describing how to use field concatenation in case the user does not care about the performance impact
Why
Currently, whenever you pass a value in the order_by argument, the paginator takes care of building a unique cursor by concatenating the order_by column and the id.
sql =
if custom_order_field?
"CONCAT(#{@order_field}, '-', #{id_column})"
else
id_column
endSince it is not possible to add an index on a computed value like concat(field, other_field), this can lead to performance issues, when paginating on big tables. See this article for more details about performance in cursor pagination.
For this reason the responsibility of ordering by a unique attribute should me moved outside of the gem. When using the gem, if you need to order by a column that is not unique, you should find the best solution for you to make it unique, and pass that to the paginator.
This could be done by adding a new column to the table that represents the wanted ordering and is unique, or similarly using a view.
To allow ordering by a non unique column, without changing the database, the gem should allow to order by a SQL statement.
Paginator.new(..., order_by: "concat('name','-','id')", ...)This would still ensure the pagination works correctly, since it will order and filter by a unique cursor, but it could lead to performance issues, since there is no index on the cursor.