Skip to content

Use order_by argument as cursor #3

@domangi

Description

@domangi

What

  • The order_by argument should accept not only field names, but also sql statements, e.g. CONCAT(field, otherfield) or FIELD(field, 'value1', 'value2')
  • The order_by value, which defaults to id, 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_by column 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
    end

Since 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.

Metadata

Metadata

Labels

bugSomething isn't workingenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions