Browse all documentation

Querying data

Limited

Find, filter, sort, paginate, and populate content with one query language from Go, TypeScript, and REST.

Every read in Ridu uses one query language. The Local Go API, the TypeScript SDK, REST and your access rules all build the same filters, so each example below shows all three. Pick a tab once and the rest of the docs follow it.

Example schema

The examples query this posts collection. Each post’s author is a document in users, which has a name field.

content/posts.go
var Posts = ridu.Collection{
  Slug: "posts",
  Fields: field.Fields{
    field.Text("title").Required(),
    field.Select("status", "draft", "published").
      Default("draft"),
    field.Relationship("author", "users"),
    field.TextList("tags"),
    field.Group("seo", field.Fields{
      field.Text("title"),
      field.Textarea("description"),
    }),
    field.Date("publishedAt"),
    field.Number("views"),
  },
}

Each tab assumes a little setup:

Tab Uses
Go local, the Local Go API from app.Local() or a hook’s ctx.Local, and user, the signed-in caller’s document (why).
TypeScript ridu, a generated client.
REST $RIDU, the server’s URL, and $TOKEN, a session token.

Find many

List a page of documents that match a filter:

Go
page, err := local.List(ctx, "posts", ridu.ListOptions{
  Where: query.Equal("status", "published"),
  Actor: user,
})
TypeScript
const page = await ridu.list('posts', {
  where: { status: { equals: 'published' } }
});
REST
curl -G "$RIDU/api/collections/posts" \
  -H "Authorization: Session $TOKEN" \
  --data-urlencode 'where={"status":{"equals":"published"}}'
Result, trimmed
{
  "docs": [
    {
      "id": "posts_49d8d5f5eebb60b11c3fd9f9",
      "title": "Hello, Ridu",
      "status": "published",
      "author": "users_c15d8cdad9e97e3c8ba53543",
      "tags": ["launch", "go"],
      "publishedAt": "2026-09-01",
      "views": 1200
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "totalDocs": 3,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

In Go, page.Documents holds the documents, and page.Total and page.HasNextPage hold the pagination. Change the page, its size and its order in Sorting and pagination.

Find one

Read one document by ID:

Go
post, err := local.Find(ctx, "posts", postID, ridu.FindOptions{
  Actor: user,
})
TypeScript
const post = await ridu.find('posts', postID);
REST
curl "$RIDU/api/collections/posts/$POST_ID" \
  -H "Authorization: Session $TOKEN"

A missing document, or one the caller can’t read, fails with not_found: a *ridu.OperationError in Go, a RiduError in TypeScript, and a 404 over REST.

Count

Count the documents that match a filter, without reading them:

Go
// Go has no separate count: read one document and its total.
page, err := local.List(ctx, "posts", ridu.ListOptions{
  Where: query.In("tags", "guide"),
  Limit: 1,
  Actor: user,
})
total := *page.Total
TypeScript
const { totalDocs } = await ridu.count('posts', {
  where: { tags: { in: ['guide'] } }
});
REST
curl -G "$RIDU/api/collections/posts/count" \
  -H "Authorization: Session $TOKEN" \
  --data-urlencode 'where={"tags":{"in":["guide"]}}'
Result
{ "totalDocs": 2 }

Read a global

A global is a single document, such as site settings, so you read it by its slug:

Go
settings, err := local.Global(ctx, "site-settings", ridu.FindOptions{
  Actor: user,
})
TypeScript
const settings = await ridu.global('site-settings');
REST
curl "$RIDU/api/globals/site-settings" \
  -H "Authorization: Session $TOKEN"

Shape the results

Every read takes the same options. Each has a guide:

To… Go (ListOptions) TypeScript and REST Guide
keep only matching documents Where where Filters
order them Sort sort Sorting and pagination
pick a page Page, Limit page, limit Sorting and pagination
skip counting every match SkipTotal pagination: false Sorting and pagination
return only some fields Select select Selecting and populating
include related documents Populate populate, depth Selecting and populating
read another content locale Locale, FallbackLocales locale, fallbackLocale Localization
read drafts or the published version Draft draft Drafts and versions
read deleted documents TrashOnly trash Bulk actions and trash

Find takes the options that apply to one document: selection, population, locale, draft and trash. A count takes the filter, locale, draft and trash options.

Locales, drafts and trash

Reads use the request’s content locale and its fallbacks for filters, sorting and population as well as output. Pass locale: 'all' to get every locale’s values at once; see Localization.

On a collection with drafts, a read returns the draft when the caller may read drafts, and the published version otherwise. Set draft to choose explicitly; see Drafts and versions.

Deleted documents in a trash-enabled collection stay out of ordinary reads. Set trash: true (TrashOnly in Go) to read only deleted documents; one query can’t mix the two.

How access rules apply

A collection’s read rule can return a filter instead of a yes or no. Ridu adds it to your where in the same database query, so a page never contains documents the caller can’t read, and the totals count only documents they can. A field with a read rule can’t be filtered or sorted, even by callers who can read it. See Access control.

Current limits

There is no notIn operator (wrap in in not instead), full-text ranking, operator that requires every item of a list, or geospatial query. A point field can be stored and returned, but not queried by distance. Distinct values are available only from Go, for one direct field; see Distinct values.

For query performance, indexes and population cost, see Database and query performance.