---
title: 0.11.0
---

## Brand New Query API ✨

[#1739](https://github.com/paradedb/paradedb/pull/1739) by [@eeeebbbbrrrr](https://github.com/eeeebbbbrrrr) brought a custom scan implementation to `pg_search`.
Barring the technical details, this PR centers the entire ParadeDB search API around the `@@@` operator. The old `.search()` syntax has been removed in
[#1781](https://github.com/paradedb/paradedb/pull/1781) by [@neilyio](https://github.com/neilyio) and the documentation has been overhauled.

<Note>
  By upgrading to `0.11.0`, any queries that rely on the old search syntax will
  need to be rewritten.
</Note>

```sql
-- Old query syntax
SELECT description, rating, category
FROM search_idx.search(
  '(description:keyboard OR category:electronics) AND rating:>2',
  limit_rows => 5
);

-- New query syntax
SELECT description, rating, category
FROM mock_items
WHERE (description @@@ 'shoes' OR category @@@ 'footwear') AND rating @@@ '>2'
ORDER BY description
LIMIT 5;
```

This new query syntax brings a number of serious benefits:

### JOIN Friendly

The old `.search()` syntax made it difficult to search over joined tables. The `@@@` operator, on the other hand, acts like any other Postgres operator
and can be dropped into both sides of a JOIN query:

```sql
SELECT o.order_id
FROM orders o
JOIN mock_items m ON o.product_id = m.id
WHERE o.customer_name @@@ 'Johnson' AND m.description @@@ 'shoes';
```

### Intuitive SQL Syntax

The `@@@` operator relies on SQL `LIMIT`, `OFFSET`, and `ORDER BY` clauses for limits, offsets, and sorting. These parameters no longer need to be passed in
as arguments to the `.search()` function.

### Direct Scores and Snippets

The old `.score_bm25()` and `.snippet()` functions needed to be JOINed with the original tables to associate rows with their scores/snippets. This is no longer the
case with the custom scan, which is capable of projecting scores and snippets directly onto the result table:

```sql
-- BM25 scoring
SELECT id, paradedb.score(id)
FROM mock_items
WHERE description @@@ 'shoes';

-- Snippets
SELECT id, paradedb.snippet(description)
FROM mock_items
WHERE description @@@ 'shoes';
```

## Performance Improvements 🚀

### Incredibly Efficient Top N Queries

[#1765](https://github.com/paradedb/paradedb/pull/1765) brought significant performance improvements to "top N" style search queries:

```sql
-- Top 5 results by score
SELECT id, paradedb.score(id)
FROM mock_items
WHERE description @@@ 'shoes'
LIMIT 5;
```

On test datasets with 1 billion+ rows, we've seen query times drop from over 10 seconds to under 20 milliseconds.

### Concurrent Writes

[#1707](https://github.com/paradedb/paradedb/pull/1707) brought concurrent writes to multiple indexes. Prior to this change, a write to one index
would block writes to any other index. This PR also removes the background writer from `pg_search`, which significantly reduces the surface area for bugs.

## Query Builder 💡

### JSON Support

Query builder term, phrase, and range functions can now query [JSON fields](/documentation/advanced/json/overview) in the same way as text fields.

```sql
-- Queries {"metadata": {"color": "white"}}
SELECT description, rating, category
FROM mock_items
WHERE id @@@ paradedb.term('metadata.color', 'white');
```

### Range Term

Columns of type `int4range`, `int8range`, `numrange`, `tsrange`, and `tstzrange` can be indexed as `range_fields`.
The [range term](/documentation/advanced/term/range_term) query is used to filter over these fields.

```sql
CALL paradedb.create_bm25(
  index_name => 'search_idx',
  table_name => 'mock_items',
  key_field => 'id',
  range_fields => paradedb.field('weight_range')
);

SELECT id, weight_range FROM mock_items
WHERE id @@@ paradedb.range_term('weight_range', 1);
```

### Parse

`paradedb.parse` now accepts `lenient` and `conjunction_mode` parameters. A [new function](/documentation/advanced/compound/parse), `paradedb.parse_with_field`, has also been introduced.

## Stability Improvements 💪

### Flat JSONB Arrays

Fixed a bug where `paradedb.term` failed to search over flat JSONB arrays like `'["red", "blue", "green"]'::JSONB`.

### Prepared Statements

Fixed a bug where prepared statements using the `@@@` operator would incorrectly choose a sequential scan.

## Docker Image 🐳

The ParadeDB Docker image is now available for all versions of Postgres from 13 to 17. Previously, only Postgres 16 was available.

## New Contributors 👋

- [@ethe](https://github.com/ethe) made their first contribution in [#1756](https://github.com/paradedb/paradedb/pull/1756)

## Full Changelog

The full changelog is available [here](https://github.com/paradedb/paradedb/releases/tag/v0.11.0).
