powered by

Search records across your entities

Product overview →

Full-text search across your entities from the dashboard, CLI or REST API: pick searchable fields, filter and sort, find similar records, and search publicly.

Last updated

Anythink keeps a search index of your records, powered by Meilisearch. Every time you create, update or delete a record the index is updated in the background, so there is nothing to set up beyond choosing which fields are searchable. One query can search every entity in your project at once, or just the ones you name. It handles typos, ranks the best matches first, and can filter, sort, count and highlight.

There are two ways in:

Signed-in search Public search
Endpoint GET /org/{project_id}/search GET /org/{project_id}/search/public
Needs a token Yes, a signed-in user No
Fields returned The whole record Only publicly searchable fields
Row-level security Applied Not applicable: public fields only
Use it for Your own app, once people have signed in A blog, docs site or catalogue anyone can search

Your project ID is the number after /org/ in the dashboard address. The examples use https://api.my.anythink.cloud as the API URL. For how users get a token, see Sign in users.

What search covers

Search covers the fields you mark as searchable, on every entity in the project. Two flags on each field control it:

Flag In the dashboard What it does
is_searchable Searchable The field's text is matched by search. The field can also be used to filter, sort and count (facets).
publicly_searchable Publicly Searchable The field is also matched by public search, and returned in its results. Only available on a searchable field.

A few rules sit on top of that:

  • The name field. The field you mark as the entity's name field is the record's label. Search always matches it, and ranks matches in it highest. Signed-in results carry it as __name. In the dashboard, ticking Name field ticks Searchable for you.
  • id is always searchable, so searching for a record's ID finds it.
  • Ranking. A match in the name field beats a match in a text field, which beats a match in any other searchable field, which beats a match in a related record's name.
  • Relationships. A searchable many-to-one, one-to-one or user field is matched on the name of the record it points to. Searching for an author's name finds their articles.
  • Fields you leave off. A field that isn't searchable is never matched. It can still appear in a signed-in search result, because those return the whole record.
  • No setup for new records. Indexing is automatic.

In the Anythink dashboard

  1. Open Settings › Data Model and choose the entity.
  2. Open a field, or add a new one.
  3. In the Performance & API card, tick Searchable. Tick Publicly Searchable as well if anonymous visitors should be able to search it.
  4. Save the field.

Back on the entity's field list, small badges show the flags: S for searchable, PS for publicly searchable and NF for the name field.

To search from anywhere in the dashboard, press Cmd+K (Ctrl+K on Windows and Linux), and type into Search for anything.... It runs a signed-in search across all your entities.

With the CLI

bash
# Add a searchable field, public as well
anythink fields add articles title --type varchar --name-field --searchable --public

# Change an existing field
anythink fields update articles body --searchable
anythink fields update articles status --searchable --public

# Turn the flags off again
anythink fields update articles body --no-searchable
anythink fields update articles status --no-public

--public sets Publicly Searchable. Check the result with anythink fields list articles.

With an AI assistant (MCP)

text
On the articles entity, make title and body searchable, and make title and status publicly searchable.

The assistant runs fields update through the cli tool for each field. Connect an AI assistant sets up the MCP server. Field types are covered in Field types.

Search from the API

Send the signed-in user's access token and a query:

http
GET /org/{project_id}/search?q=espresso&e=articles
Authorization: Bearer <access token>
json
{
  "items": [
    {
      "id": "1",
      "created_at": "2026-10-04T13:38:09.288332Z",
      "updated_at": "2026-10-04T13:38:09.288332Z",
      "title": "Espresso guide",
      "body": "Grind fine and pull a double shot",
      "status": "published",
      "__name": "Espresso guide",
      "__entity": "articles",
      "__url": "/org/{project_id}/entities/articles/items/1"
    }
  ],
  "page": 1,
  "page_size": 20,
  "total_items": 1,
  "total_pages": 1,
  "has_next_page": false,
  "has_previous_page": false,
  "retrieval_time": 4,
  "facet_distribution": null
}

Each item is the record, plus __entity (the entity it came from), __url (the path to the record) and __name (its name field). retrieval_time is milliseconds spent searching. Results from several entities arrive in one list, and __entity tells you which is which.

Parameter Meaning
q The search text. Leave it out, or send *, to match everything.
e Comma-separated entity names to search, such as e=articles,products. Leave it out to search every entity.
q=field:text Search a single field. q=title:espresso matches espresso in title only. An entity without that searchable field is skipped.
s Sort, such as s=created_at:desc. See filters and sorting.
fl A filter expression, such as fl=status = published.
f Comma-separated fields to count values for (facets), such as f=status,category.
hl hl=true adds a _formatted copy of each record with matches wrapped in <mark> tags.
page Page number, starting at 1. Default 1.
pageSize Results per page, 1 to 100. Default 20.

Text before a colon in q is read as a field name, so leave colons out of free-text queries.

In the Anythink dashboard

Use the Cmd+K search box for quick lookups. Filters, sorting, facets and highlighting are API features: the dashboard's search box sends the text only.

With the CLI

bash
anythink search query espresso
anythink search query espresso --entities articles
anythink search query "*" --entities articles --filter "status = published" --sort "created_at:desc" --limit 10
anythink search query espresso --entities articles --facet status --highlight --page 2
anythink search query espresso --json
Option Sends
--entities <LIST> e
--filter <EXPR> fl
--sort <LIST> s
--facet <FIELDS> f
--highlight hl=true
--page <N>, --limit <N> page, pageSize (1 to 100)
--public Uses /search/public instead
--json Prints the raw response

Without --json the CLI prints each match as entity/id — name, with its created time and URL, and a page footer when there is more than one page. anythink fetch calls the endpoint directly if you want the raw HTTP: anythink fetch "/search?q=espresso&e=articles".

With an AI assistant (MCP)

text
Search my articles for espresso and show the three newest published ones.

The assistant runs search query espresso --entities articles --filter "status = published" --sort "created_at:desc" --limit 3 through the cli tool. See MCP tool reference.

Search without signing in

For a blog, documentation site or catalogue where visitors aren't signed in, call the public endpoint. It takes no token and the same q, e, s, fl, f, page and pageSize parameters:

http
GET /org/{project_id}/search/public?q=espresso&e=articles
json
{
  "items": [
    {
      "id": "1",
      "created_at": "2026-10-04T13:38:09.288332Z",
      "updated_at": "2026-10-04T13:38:09.288332Z",
      "title": "Espresso guide",
      "status": "published",
      "__entity": "articles",
      "__url": "/org/{project_id}/entities/articles/items/1"
    }
  ],
  "page": 1,
  "page_size": 20,
  "total_items": 1,
  "total_pages": 1,
  "has_next_page": false,
  "has_previous_page": false,
  "retrieval_time": 0,
  "facet_distribution": null
}

What public search does differently:

  • It only matches publicly searchable fields. Text in a field that is only Searchable is never matched, so a visitor can't discover it by guessing words.
  • It only returns publicly searchable fields, plus five default fields on every result: id, created_at, updated_at, __entity and __url. In the example, body is searchable but not public, so it is absent.
  • It only searches entities with at least one publicly searchable field (other than id). Entities without one never appear, even if you name them in e.
  • A field search such as q=title:espresso only works on a publicly searchable field. Any other field returns no results.

Treat everything in a publicly searchable field as public. Before you open a site to visitors, mark only the fields you'd be happy to show on a web page.

In the Anythink dashboard

Turn on Publicly Searchable for the fields you want to expose, as described in What search covers. Keep Searchable only on fields that are for signed-in users.

With the CLI

bash
anythink search query espresso --public
anythink search query "*" --public --entities articles --limit 5
anythink search audit articles

search audit runs the same query publicly and signed in, and reports whether the public results contain any field you haven't marked publicly searchable. Run it after changing which fields are public.

With an AI assistant (MCP)

text
Check what an anonymous visitor can search on the articles entity, and list the fields that are public.

The assistant runs search query with --public and search audit articles through the cli tool.

Filters and sorting

Filters use Meilisearch's expression syntax and go in the fl parameter. Your filter is combined with a restriction to your project, so it can only narrow results.

You want Filter
Equals status = published
Not equal status != draft
One of several values status IN [published, scheduled]
Both conditions status = published AND category = news
Either condition status = draft OR status = scheduled
Negate NOT status = draft
Number comparison id > 100, id >= 10 AND id < 50
Has a value subtitle EXISTS

Quote values that contain spaces: title = "Cold brew notes". URL-encode the whole expression when you build the URL by hand.

You can filter, sort and count (f) on:

  • Every field marked Searchable.
  • The record's id, created_at and updated_at.
  • Your many-to-one, one-to-one and user fields, searchable or not.

Filtering on any other field returns an error, so mark the field searchable first.

Sorting. Give s one or more field:direction pairs, comma separated: s=created_at:desc,id:asc. Direction is asc or desc. Sort fields that aren't searchable are ignored, and results then come back in relevance order. Without s, results are ranked by relevance.

Facets. f=status returns a count of each value of status among the matches, in facet_distribution:

json
"facet_distribution": {
  "status": { "draft": 1, "published": 2 }
}

Counts from several entities are added together. That makes facets good for category filters and tag lists on a search page.

Geo fields. If an entity has a geo field, you can also filter with _geoRadius(lat, lng, distanceInMeters) or _geoBoundingBox([lat, lng], [lat, lng]), and sort with _geoPoint(lat, lng):asc.

Find similar records

Anythink also builds a semantic (vector) index of each entity from its searchable text fields and related names, so it can find records with similar meaning, even without shared keywords. Use it for "more like this" and "related articles".

http
GET /org/{project_id}/search/similar?e=articles&id=1&limit=10
Authorization: Bearer <access token>

The response is a list of records, most similar first, not wrapped in the paginated shape:

json
[
  {
    "id": "3",
    "title": "Espresso machines compared",
    "body": "Pump pressure and boiler types",
    "status": "published",
    "__name": "Espresso machines compared",
    "__entity": "articles",
    "__url": "/org/{project_id}/entities/articles/items/3"
  }
]
Parameter Meaning
e The entity name. Required.
id The record to find neighbours of. Required.
limit How many to return. Default 10.

An unknown entity or a record that isn't indexed returns 404. The source record itself isn't included. If the entity uses row-level security, records you can't read are removed, so you may get fewer than limit.

In the Anythink dashboard

The dashboard has no "similar records" screen. Use the CLI or the API.

With the CLI

bash
anythink search similar articles 1
anythink search similar articles 1 --limit 5 --json

With an AI assistant (MCP)

text
Find articles similar to article 1.

The assistant runs search similar articles 1 through the cli tool.

Search respects who is asking.

  • Signed-in search applies row-level security. For an entity with row-level security on, each matching record is checked against the signed-in user, and records they aren't allowed to read are removed from the results. Entities without row-level security return all matches. A page can therefore hold fewer items than pageSize.
  • Public search never depends on a user. It returns only publicly searchable fields. Don't put anything in a publicly searchable field that you wouldn't show an anonymous visitor, even on an entity that uses row-level security.
  • Similar records follow the same rule as signed-in search.

How access is granted is covered in Groups and row-level security and Roles and permissions.

Rebuild the search index

Rehydrating re-sends every record of an entity, or of the whole project, from your database to the search index. Existing entries are replaced and no data is lost. It runs in the background, so results can look incomplete until it finishes. Only a project administrator can start one.

Task Endpoint Response
Rehydrate every entity POST /org/{project_id}/search/rehydrate 204 No Content
Rehydrate one entity POST /org/{project_id}/search/rehydrate/{entity_name} 204 No Content

In the Anythink dashboard

  1. Open Settings › Operations.
  2. Under Search Operations, click Rehydrate Search Data for everything, or use the Rehydrate button beside one entity.
  3. Confirm. A message tells you the job has been queued.

The same page has a Purge button, which empties the index. Rehydrate afterwards to fill it again.

With the CLI

bash
anythink search rehydrate articles
anythink search rehydrate --yes

Without --yes the CLI asks you to confirm. Leave out the entity to rehydrate everything. anythink search purge [entity] empties the index in the same way, and you then run search rehydrate to repopulate it.

With an AI assistant (MCP)

text
Rehydrate the search index for the articles entity.

The assistant runs search rehydrate articles --yes through the cli tool. Ask it to check with you first if you'd like a confirmation step.

Limits

Limit Detail
Results per page 1 to 100. Default 20.
Reachable results 1,000 per query for each entity. Narrow the query with q, e or fl instead of paging deeper.
Page number 1 or more.
Similar records limit defaults to 10.
Filter, sort and facet fields Searchable fields, relationship fields, and id, created_at, updated_at.
Public search Publicly searchable fields only, plus id, created_at, updated_at, __entity and __url.
Index updates Background, so a change is searchable a moment after you save it.
Rehydrate and purge Project administrators only.
Who can call signed-in search A signed-in user with access to the project.

Next steps