prax-orm 0.11.0

A next-generation, type-safe ORM for Rust inspired by Prisma
Documentation
---
import DocsLayout from '../../layouts/DocsLayout.astro';
import CodeBlock from '../../components/CodeBlock.astro';

const offsetPagination = `// Skip and take (offset pagination)
let page = 2;
let page_size = 20;

let users = client
    .user()
    .find_many()
    .skip((page - 1) * page_size)
    .take(page_size)
    .exec()
    .await?;

// Get total count for pagination UI
let total = client
    .user()
    .count()
    .exec()
    .await?;

let total_pages = (total + page_size - 1) / page_size;`;

const cursorPagination = `use prax_query::pagination::Cursor;

// Cursor-based pagination (more efficient for large datasets)
let users = client
    .user()
    .find_many()
    .cursor(Cursor::after("id", last_id))
    .take(20)
    .exec()
    .await?;

// Fetch the previous page instead with Cursor::before("id", first_id)

// Get the cursor for the next page
let next_cursor = users.last().map(|u| u.id);`;

const sorting = `use prax_query::types::{NullsOrder, OrderByField};

// Single field sort
let users = client
    .user()
    .find_many()
    .order_by(OrderByField::desc("created_at"))
    .exec()
    .await?;

// Multiple field sort — pass a field list to one .order_by() call
// (a second .order_by() call replaces the first)
let users = client
    .user()
    .find_many()
    .order_by(vec![
        OrderByField::asc("last_name"),
        OrderByField::asc("first_name"),
    ])
    .exec()
    .await?;

// Nulls first/last
let users = client
    .user()
    .find_many()
    .order_by(OrderByField::desc("deleted_at").nulls(NullsOrder::First))
    .exec()
    .await?;`;

const distinct = `// Get distinct values
let cities = client
    .user()
    .find_many()
    .distinct(["city"])
    .exec()
    .await?;

// Distinct on multiple fields
let locations = client
    .user()
    .find_many()
    .distinct(["country", "city"])
    .exec()
    .await?;

// Generated field modules also expose the column name as a const:
// .distinct([user::city::COLUMN])`;
---

<DocsLayout title="Pagination &amp; Sorting - Prax ORM">
  <article class="max-w-4xl mx-auto px-6 py-12">
    <header class="mb-12">
      <h1 class="text-4xl font-bold mb-4">Pagination &amp; Sorting</h1>
      <p class="text-xl text-muted">
        Paginate results and order them efficiently.
      </p>
    </header>

    <div class="space-y-12">
      <section>
        <h2 class="text-2xl font-semibold mb-4">Offset Pagination</h2>
        <CodeBlock code={offsetPagination} lang="rust" />
      </section>

      <section>
        <h2 class="text-2xl font-semibold mb-4">Cursor Pagination</h2>
        <p class="text-muted mb-4">
          With a cursor and no explicit <code class="text-primary-400">.order_by(...)</code>, the query
          automatically orders by the cursor column (<code>Cursor::after</code> &rarr; ASC,
          <code>Cursor::before</code> &rarr; DESC) so keyset pagination stays deterministic;
          an explicit <code class="text-primary-400">.order_by(...)</code> takes precedence.
        </p>
        <CodeBlock code={cursorPagination} lang="rust" />
      </section>

      <section>
        <h2 class="text-2xl font-semibold mb-4">Sorting</h2>
        <CodeBlock code={sorting} lang="rust" />
      </section>

      <section>
        <h2 class="text-2xl font-semibold mb-4">Distinct</h2>
        <p class="text-muted mb-4">
          <code class="text-primary-400">.distinct(cols)</code> emits
          <code>SELECT DISTINCT ON (cols)</code> on PostgreSQL. Other dialects fall back to plain
          <code>SELECT DISTINCT</code>, which deduplicates whole rows &mdash; different semantics.
        </p>
        <CodeBlock code={distinct} lang="rust" />
      </section>
    </div>
  </article>
</DocsLayout>