Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ export const gettingstarted: NavMenuConstant = {
url: '/guides/getting-started',
items: [
{ name: 'Features', url: '/guides/getting-started/features' },
{ name: 'API Keys', url: '/guides/getting-started/api-keys' },
{ name: 'Architecture', url: '/guides/getting-started/architecture' },
{
name: 'Framework Quickstarts',
Expand Down Expand Up @@ -1492,9 +1493,7 @@ export const api: NavMenuConstant = {
name: 'Security',
url: '/guides/api',
items: [
{ name: 'How API Keys work', url: '/guides/api/api-keys' },
{ name: 'Securing your API', url: '/guides/api/securing-your-api' },
{ name: 'Data API', url: '/guides/database/data-api' },
{
name: 'Custom Claims & RBAC',
url: '/guides/api/custom-claims-and-role-based-access-control-rbac',
Expand Down Expand Up @@ -2485,7 +2484,7 @@ export const security: NavMenuConstant = {
url: '/guides/deployment/shared-responsibility-model' as `/${string}`,
},
{ name: 'Row Level Security', url: '/guides/database/postgres/row-level-security' },
{ name: 'Data API', url: '/guides/database/data-api' },
{ name: 'Securing your API', url: '/guides/api/securing-your-api' },
],
},
],
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/_partials/api_settings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Now that you've created some database tables, you are ready to insert data using

To do this, you need to get the Project URL and key from [the project **Connect** dialog](/dashboard/project/\_?showConnect=true&connectTab={{ .tab }}&framework={{ .framework }}).

[Read the API keys docs](/docs/guides/api/api-keys) for a full explanation of all key types and their uses.
[Read the API keys docs](/docs/guides/getting-started/api-keys) for a full explanation of all key types and their uses.

<Admonition type="note" title="Changes to API keys">

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/_partials/api_settings_steps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Now that you've created some database tables, you are ready to insert data using

To do this, you need to get the Project URL and key from [the project **Connect** dialog](/dashboard/project/\_?showConnect=true&connectTab={{ .tab }}&framework={{ .framework }}).

[Read the API keys docs](/docs/guides/api/api-keys) for a full explanation of all key types and their uses.
[Read the API keys docs](/docs/guides/getting-started/api-keys) for a full explanation of all key types and their uses.

<Admonition type="note" title="Changes to API keys">

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/_partials/metrics_access.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ className="rounded-lg border border-foreground/10 bg-surface-100 text-foreground
3. Authenticate with HTTP Basic Auth:

- **Username**: `service_role`
- **Password**: a **Secret API key** (`sb_secret_...`). You can create/copy it in [**Project Settings → API Keys**](/dashboard/project/_/settings/api-keys). For more context, see [Understanding API keys](/docs/guides/api/api-keys).
- **Password**: a **Secret API key** (`sb_secret_...`). You can create/copy it in [**Project Settings → API Keys**](/dashboard/project/_/settings/api-keys). For more context, see [Understanding API keys](/docs/guides/getting-started/api-keys).

Testing locally is as simple as running `curl` with your Secret API key:

Expand Down
50 changes: 50 additions & 0 deletions apps/docs/content/guides/ai/semantic-search.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,56 @@ from match_documents(

In this scenario, you'll likely use a Postgres client library to establish a direct connection from your application to the database. It's best practice to parameterize your arguments before executing the query.

### Filtering vector search by metadata

In real applications you usually want to combine the similarity search with a filter on another column, for example only matching documents in a given category, owned by a specific user, or carrying matching metadata in a `jsonb` column. The recommended pattern is to push the filter into the SQL function so the planner can combine it with the vector predicate. Chaining `.eq()` after `rpc()` is applied by PostgREST as an outer filter on the function's result, _after_ the function has already executed its similarity ranking and `limit` — so the vector planner can't use it, and selective filters can leave you with fewer than `match_count` rows.

Assuming you've added a `category text` column to `documents`, you can extend the cosine variant of `match_documents` with a typed filter parameter:

```sql
-- Match documents in a given category using cosine distance (<=>)
create or replace function match_documents (
query_embedding extensions.vector(512),
match_threshold float,
match_count int,
filter_category text
)
returns setof documents
language sql
as $$
select *
from documents
where documents.category = filter_category
and documents.embedding <=> query_embedding < 1 - match_threshold
order by documents.embedding <=> query_embedding asc
limit least(match_count, 200);
$$;
```

If you store side data in a `jsonb metadata` column instead of dedicated columns, the same pattern works with the `@>` containment operator:

```sql
where documents.metadata @> filter_metadata
and documents.embedding <=> query_embedding < 1 - match_threshold
```

Call the filtered function from your application by passing the extra parameter:

```tsx
const { data: documents } = await supabase.rpc('match_documents', {
query_embedding: embedding,
match_threshold: 0.78,
match_count: 10,
filter_category: 'blog',
})
```

<Admonition type="note">

When the filter is selective enough that the post-filter result set falls below `match_count`, an HNSW index can return fewer rows than expected. From `pgvector` 0.8.0, the planner supports iterative index scans that re-enter the index to gather more candidates. See [Filtering with HNSW indexes](/docs/guides/ai/vector-indexes/hnsw-indexes#filtering-with-hnsw-indexes) for details.

</Admonition>

## Next steps

As your database scales, you will need an index on your vector columns to maintain fast query speeds. See [Vector indexes](/docs/guides/ai/vector-indexes) for an in-depth guide on the different types of indexes and how they work.
Expand Down
6 changes: 6 additions & 0 deletions apps/docs/content/guides/ai/vector-columns.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ In this example `embedding` would be another embedding you wish to compare again

<Admonition type="tip">

To filter your vector search by another column from the JS client, extend the function above with an extra parameter and `where` clause. See [Filtering vector search by metadata](/docs/guides/ai/semantic-search#filtering-vector-search-by-metadata) for a worked example.

</Admonition>

<Admonition type="tip">

Be sure to use embeddings produced from the same embedding model when calculating distance. Comparing embeddings from two different models will produce no meaningful result.

</Admonition>
Expand Down
13 changes: 13 additions & 0 deletions apps/docs/content/guides/ai/vector-indexes/hnsw-indexes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,19 @@ HNSW should be your default choice when creating a vector index. Add the index w

Unlike IVFFlat indexes, you are safe to build an HNSW index immediately after the table is created. HNSW indexes are based on graphs which inherently are not affected by the same limitations as IVFFlat. As new data is added to the table, the index will be filled automatically and the index structure will remain optimal.

## Filtering with HNSW indexes

Adding a `where` clause to a vector query does not bypass the HNSW index. The Postgres planner picks between using the index and a sequential scan based on the selectivity of the filter and the size of the table. When the index is used, the filter is applied as the index returns candidates.

The trade-off shows up when the filter is selective: an HNSW scan returns the top `k` rows by distance, and if most of those are filtered out you can end up with fewer rows than your `LIMIT`. From `pgvector` 0.8.0, the planner supports **iterative index scans** that automatically scan more of the index until enough results are found, controlled by the `hnsw.iterative_scan` GUC. The default is `off`. The two enabled modes are:

- `strict_order` preserves exact distance ordering across iterations.
- `relaxed_order` allows slight reordering across iterations for better recall.

`hnsw.max_scan_tuples` (default 20,000) and `hnsw.scan_mem_multiplier` (default 1) bound how far the iterative scan goes. See the [pgvector iterative scans documentation](https://github.com/pgvector/pgvector#iterative-index-scans) for the full reference.

For an end-to-end JavaScript example of filtering a vector search by another column, see [Filtering vector search by metadata](/docs/guides/ai/semantic-search#filtering-vector-search-by-metadata).

## Resources

Read more about indexing on `pgvector`'s [GitHub page](https://github.com/pgvector/pgvector#indexing).
28 changes: 13 additions & 15 deletions apps/docs/content/guides/api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,25 @@ The API is auto-generated from your database and is designed to get you building

You can use them directly from the browser (two-tier architecture), or as a complement to your own API server (three-tier architecture).

<Admonition type="tip" title="Looking for your Data API URL and Keys?">

- You can find the API URL in the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/overview) section of the Dashboard.
- You can find the API Keys in the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard.

</Admonition>

## Features [#rest-api-overview]

Supabase provides a RESTful API using [PostgREST](https://postgrest.org/). This is a very thin API layer on top of Postgres.
Supabase provides a RESTful API using [PostgREST](https://postgrest.org/), a thin API layer on top of Postgres.
It exposes everything you need from a CRUD API at the URL `https://<project_ref>.supabase.co/rest/v1/`.

The REST interface is automatically reflected from your database's schema and is:

- **Instant and auto-generated.** <br />As you update your database the changes are immediately accessible through your API.
- **Self documenting.** <br />Supabase generates documentation in the Dashboard which updates as you make database changes.
- **Secure.** <br />The API is configured to work with Postgres's Row Level Security, provisioned behind an API gateway with key-auth enabled.
- **Fast.** <br />Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting.
- **Scalable.** <br />The API can serve thousands of simultaneous requests, and works well for Serverless workloads.
- **Instant and auto-generated:** As you update your database the changes are immediately accessible through your API.
- **Self documenting:** Supabase generates documentation in the Dashboard which updates as you make database changes.
- **Secure:** The API is configured to work with Postgres's Row Level Security, provisioned behind an API gateway with key-auth enabled.
- **Fast:** Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting.
- **Scalable:** The API can serve thousands of simultaneous requests, and works well for Serverless workloads.

The reflected API is designed to retain as much of Postgres' capability as possible including:

Expand All @@ -35,12 +42,3 @@ The reflected API is designed to retain as much of Postgres' capability as possi
- The Postgres security model - including Row Level Security, Roles, and Grants.

The REST API resolves all requests to a single SQL statement leading to fast response times and high throughput.

Reference:

- [Docs](https://postgrest.org/)
- [Source Code](https://github.com/PostgREST/postgrest)

## API URL and keys

You can find the API URL and Keys in the [Dashboard](/dashboard/project/_/settings/api-keys).
2 changes: 1 addition & 1 deletion apps/docs/content/guides/api/creating-routes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ In most cases, you can get the correct key from [the Project's **Connect** dialo

</Admonition>

[Read the API keys docs](/docs/guides/api/api-keys) for a full explanation of all key types and their uses.
[Read the API keys docs](/docs/guides/getting-started/api-keys) for a full explanation of all key types and their uses.

The REST API is accessible through the URL `https://<project_ref>.supabase.co/rest/v1`

Expand Down
Loading
Loading