> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paradedb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Querying Vectors

> Run nearest-neighbor vector search inside the ParadeDB index

<Note>
  This is a beta feature available in versions `0.25.0` and above. See [How
  Vector Search Works](/documentation/vector/overview) for background, and
  [Indexing Vectors](/documentation/indexing/indexing-vectors) to set up the
  index used in these examples.
</Note>

Vector search returns the rows whose embeddings are closest to a query vector. In ParadeDB, this is an `ORDER BY <distance> ... LIMIT k` query over a vector column in the ParadeDB index.

When one of ParadeDB's [search operators](/documentation/filtering) is present at the same level as the `ORDER BY ... LIMIT`, ParadeDB can accelerate the vector search query.

## Unfiltered Nearest Neighbors

When you are not filtering, use `pdb.all()`, which matches every row:

<CodeGroup>
  ```sql SQL theme={null}
  SELECT id, description
  FROM mock_items
  WHERE id @@@ pdb.all()
  ORDER BY embedding <=> '[1, 2, 3, 4, 5, 6, 7, 8]'
  LIMIT 5;
  ```

  ```ts Drizzle theme={null}
  // Vector search support for Drizzle is coming very soon.
  ```

  ```python Django theme={null}
  # Vector search support for Django is coming very soon.
  ```

  ```python SQLAlchemy theme={null}
  # Vector search support for SQLAlchemy is coming very soon.
  ```

  ```ruby Rails theme={null}
  # Vector search support for Rails is coming very soon.
  ```

  ```cs EF Core theme={null}
  // Vector search support for EF Core is coming very soon.
  ```
</CodeGroup>

The `<=>` operator computes cosine distance, so this returns the five rows whose embeddings are nearest the query vector `[1, 2, 3, 4, 5, 6, 7, 8]`.

This operator must match the operator class the column was indexed with. Otherwise, ParadeDB cannot use the index to order results and falls back to a slower brute force sort.

| Operator | Distance      | Operator class      |
| -------- | ------------- | ------------------- |
| `<->`    | L2            | `vector_l2_ops`     |
| `<=>`    | Cosine        | `vector_cosine_ops` |
| `<#>`    | Inner product | `vector_ip_ops`     |

## Filtered Nearest Neighbors

To search within a subset of rows, replace `pdb.all()` with a real predicate using any of the [search operators](/documentation/filtering#non-text-fields).
For instance, the following query finds the nearest neighbors among results whose `category` contains the term `footwear`.
Note the lowercase `footwear` — the default tokenizer lowercases terms, so `Footwear` would not match.

<CodeGroup>
  ```sql SQL theme={null}
  SELECT id, description
  FROM mock_items
  WHERE category === 'footwear'
  ORDER BY embedding <=> '[1, 2, 3, 4, 5, 6, 7, 8]'
  LIMIT 5;
  ```

  ```ts Drizzle theme={null}
  // Vector search support for Drizzle is coming very soon.
  ```

  ```python Django theme={null}
  # Vector search support for Django is coming very soon.
  ```

  ```python SQLAlchemy theme={null}
  # Vector search support for SQLAlchemy is coming very soon.
  ```

  ```ruby Rails theme={null}
  # Vector search support for Rails is coming very soon.
  ```

  ```cs EF Core theme={null}
  // Vector search support for EF Core is coming very soon.
  ```
</CodeGroup>

<Note>
  Every field you filter on (e.g. `category` above) must also be part of the
  ParadeDB index. Filters on unindexed fields cannot be evaluated by the
  ParadeDB index, forcing Postgres to recheck them afterward and eliminating the
  benefit of combining vector search with [filtering](/documentation/filtering).
</Note>

## Verifying Pushdown

Use `EXPLAIN` to confirm ParadeDB is accelerating the vector search. Look for a `Custom Scan` with an `Exec Method` of `TopKScanExecState` in the query plan:

```sql theme={null}
EXPLAIN SELECT id, description
FROM mock_items
WHERE category === 'footwear'
ORDER BY embedding <=> '[1, 2, 3, 4, 5, 6, 7, 8]'
LIMIT 5;
```

<Accordion title="Expected Response">
  ```csv theme={null}
                                 QUERY PLAN
  ------------------------------------------------------------------------
   Limit
     ->  Custom Scan (ParadeDB Base Scan) on mock_items
           Table: mock_items
           Index: search_idx
           Exec Method: TopKScanExecState
           Scores: false
              TopK Order By: embedding <=> vector asc
              TopK Limit: 5
           Tantivy Query: {"with_index":{"query":{"term":{"field":"category","value":"footwear"}}}}
  ```
</Accordion>

Notice that the `category === 'footwear'` filter was pushed down into the same index scan that performs the vector search. Without pushdown, the filter would run as a separate step after the nearest neighbors were fetched.

If you do not see a `TopKScanExecState`, the query fell back to a less efficient sort. This usually means the distance operator does not match the index operator class, the query is missing a `LIMIT`, or an `ORDER BY` or filter field is not indexed.
