From f532aede62660424f1c4abe200889aea449e5189 Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:13:34 +0000 Subject: [PATCH 1/3] docs: document chained where filters combine with AND --- docs/search/filtering.mdx | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/search/filtering.mdx b/docs/search/filtering.mdx index 6602430e..7b9d9cd7 100644 --- a/docs/search/filtering.mdx +++ b/docs/search/filtering.mdx @@ -14,6 +14,37 @@ with filtering capabilities even on datasets containing billions of records. On hybrid queries, the same `where(...)` filter is applied to both the vector and full-text halves of the query. The prefilter or postfilter choice controls whether that happens before each subquery scores candidates or after the subquery top-k is produced. +## Chaining `where` clauses + +You can call `where(...)` (Python and TypeScript) or `only_if(...)` (Rust) more than once on the same query builder. Each additional filter is combined with the previous one using logical `AND`, so `where("a > 0").where("b < 10")` is equivalent to `where("(a > 0) AND (b < 10)")`. This lets you compose filters incrementally — for example, applying a shared base predicate in a helper and then adding a per-call predicate at the query site. + + +```python Python icon="python" +# Both filters apply: item is in the list AND price is above 15. +result = ( + table.search([100, 102]) + .where("item IN ('foo', 'bar', 'baz')") + .where("price > 15.0") + .limit(3) + .to_arrow() +) +``` + +```typescript TypeScript icon="square-js" +// Both filters apply: item is in the list AND price is above 15. +const result = await table + .search([100, 102]) + .where("item IN ('foo', 'bar', 'baz')") + .where("price > 15.0") + .limit(3) + .toArray(); +``` + + + +In LanceDB releases before this behavior shipped, a second `where(...)` call silently replaced the first filter, so only the last predicate was applied. If you are upgrading from an older release and previously relied on that behavior, review any code that chains `where(...)` and drop the earlier calls you no longer want to apply. + + ## Example: Metadata Filtering To illustrate filtering capabilities, let's try four data points with combinations of vectors and metadata: From d37d0705bf390611d51ae33c08d3115bdb67c083 Mon Sep 17 00:00:00 2001 From: prrao87 <35005448+prrao87@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:44:46 -0400 Subject: [PATCH 2/3] docs: clarify chained filter version boundaries --- docs/search/filtering.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/search/filtering.mdx b/docs/search/filtering.mdx index 7b9d9cd7..23d11da3 100644 --- a/docs/search/filtering.mdx +++ b/docs/search/filtering.mdx @@ -16,7 +16,9 @@ On hybrid queries, the same `where(...)` filter is applied to both the vector an ## Chaining `where` clauses -You can call `where(...)` (Python and TypeScript) or `only_if(...)` (Rust) more than once on the same query builder. Each additional filter is combined with the previous one using logical `AND`, so `where("a > 0").where("b < 10")` is equivalent to `where("(a > 0) AND (b < 10)")`. This lets you compose filters incrementally — for example, applying a shared base predicate in a helper and then adding a per-call predicate at the query site. +Starting in LanceDB Python `0.34.0` and LanceDB Rust/TypeScript `0.31.0`, you can call `where(...)` (Python and TypeScript) or `only_if(...)` (Rust) more than once on the same query builder. Each additional filter is combined with the previous one using logical `AND`, so `where("a > 0").where("b < 10")` is equivalent to `where("(a > 0) AND (b < 10)")`. + +For a fixed predicate, writing one `where(...)` clause with `AND` is just as valid and often clearer. Chaining is mainly useful when code composes filters incrementally, such as applying a shared base predicate in a helper and then adding a per-call predicate at the query site. ```python Python icon="python" @@ -42,7 +44,7 @@ const result = await table -In LanceDB releases before this behavior shipped, a second `where(...)` call silently replaced the first filter, so only the last predicate was applied. If you are upgrading from an older release and previously relied on that behavior, review any code that chains `where(...)` and drop the earlier calls you no longer want to apply. +In Python versions before `0.34.0` and Rust/TypeScript versions before `0.31.0`, a second `where(...)` or `only_if(...)` call replaced the first filter, so only the last predicate was applied. If your code needs to run on those older clients, write a single predicate with `AND` instead of chaining calls. When upgrading, review any existing chained filters and drop earlier calls you no longer want to apply. ## Example: Metadata Filtering From aa6b31a4435650d2f0d5878bc0e6f87cd1e5fd1d Mon Sep 17 00:00:00 2001 From: Prashanth Rao <35005448+prrao87@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:49:49 -0400 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Prashanth Rao <35005448+prrao87@users.noreply.github.com> --- docs/search/filtering.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/search/filtering.mdx b/docs/search/filtering.mdx index 23d11da3..350b302a 100644 --- a/docs/search/filtering.mdx +++ b/docs/search/filtering.mdx @@ -16,7 +16,7 @@ On hybrid queries, the same `where(...)` filter is applied to both the vector an ## Chaining `where` clauses -Starting in LanceDB Python `0.34.0` and LanceDB Rust/TypeScript `0.31.0`, you can call `where(...)` (Python and TypeScript) or `only_if(...)` (Rust) more than once on the same query builder. Each additional filter is combined with the previous one using logical `AND`, so `where("a > 0").where("b < 10")` is equivalent to `where("(a > 0) AND (b < 10)")`. +In more recent LanceDB SDK versions (see the callout box below for the exact version numbers), you can call `where(...)` (Python and TypeScript) or `only_if(...)` (Rust) more than once on the same query builder. Each additional filter is combined with the previous one using logical `AND`, so `where("a > 0").where("b < 10")` is equivalent to `where("(a > 0) AND (b < 10)")`. For a fixed predicate, writing one `where(...)` clause with `AND` is just as valid and often clearer. Chaining is mainly useful when code composes filters incrementally, such as applying a shared base predicate in a helper and then adding a per-call predicate at the query site. @@ -44,7 +44,7 @@ const result = await table -In Python versions before `0.34.0` and Rust/TypeScript versions before `0.31.0`, a second `where(...)` or `only_if(...)` call replaced the first filter, so only the last predicate was applied. If your code needs to run on those older clients, write a single predicate with `AND` instead of chaining calls. When upgrading, review any existing chained filters and drop earlier calls you no longer want to apply. +In Python SDK versions before `0.34.0` and Rust/TypeScript SDK versions before `0.31.0`, a second `where(...)` or `only_if(...)` call replaced the first filter, so only the last predicate was applied. If your code needs to run on those older versions, write a single predicate with `AND` instead of chaining calls. When upgrading to the latest SDKs, review any existing chained filters and drop earlier calls you no longer want to apply. ## Example: Metadata Filtering