diff --git a/docs/querying/filtering-query-results/conditional-filtering.mdx b/docs/querying/filtering-query-results/conditional-filtering.mdx
new file mode 100644
index 0000000000..7a170d169b
--- /dev/null
+++ b/docs/querying/filtering-query-results/conditional-filtering.mdx
@@ -0,0 +1,27 @@
+---
+title: "Conditional Filtering"
+sidebar_label: "Conditional Filtering"
+description: "Learn how to apply a query filter only when a condition holds, using the RQL when(condition, filter) operator, including its behavior, composition with and/or/not, parameter and null handling, type safety, and in / all in support."
+sidebar_position: 6
+supported_languages: ["csharp"]
+see_also:
+ - title: "Query Overview"
+ link: "querying/overview"
+ source: "docs"
+ path: "Querying"
+ - title: "Filter by Date and Time"
+ link: "querying/filtering-query-results/filter-by-date-and-time"
+ source: "docs"
+ path: "Querying > Filtering Query Results"
+---
+
+import LanguageSwitcher from "@site/src/components/LanguageSwitcher";
+import LanguageContent from "@site/src/components/LanguageContent";
+
+import ConditionalFilteringCsharp from './content/_conditional-filtering-csharp.mdx';
+
+
+
+
+
+
diff --git a/docs/querying/filtering-query-results/content/_conditional-filtering-csharp.mdx b/docs/querying/filtering-query-results/content/_conditional-filtering-csharp.mdx
new file mode 100644
index 0000000000..50a6e5eed4
--- /dev/null
+++ b/docs/querying/filtering-query-results/content/_conditional-filtering-csharp.mdx
@@ -0,0 +1,456 @@
+import Admonition from '@theme/Admonition';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import CodeBlock from '@theme/CodeBlock';
+import ContentFrame from '@site/src/components/ContentFrame';
+import Panel from '@site/src/components/Panel';
+
+
+
+* Conditional filtering lets a single RQL query handle different combinations of search criteria based on query parameter values,
+ instead of composing different query strings on the client.
+
+* Query parameters are values passed separately from the query text and referenced in RQL with `$`,
+ such as `$title` or `$country`.
+
+* This feature is available only in **RQL**. It is not exposed through LINQ queries or DocumentQuery.
+
+* The RQL `when(condition, predicate)` function applies a query predicate only when `condition` is true.
+ * **If `condition` evaluates to `true`** -
+ the predicate is applied.
+ * **If `condition` evaluates to `false`** -
+ the `when(...)` clause is removed from the query expression and the predicate is not applied.
+
+* The `condition` is evaluated **server-side** before documents are matched.
+ It is not evaluated per document and cannot inspect document fields.
+ The second argument, `predicate`, is a regular query predicate that is matched against documents.
+
+* In this article:
+ * [When to use conditional filtering](../../../querying/filtering-query-results/conditional-filtering.mdx#when-to-use-conditional-filtering)
+ * [Basic example](../../../querying/filtering-query-results/conditional-filtering.mdx#basic-example)
+ * [Combine `when` with `and`, `or`, and `not`](../../../querying/filtering-query-results/conditional-filtering.mdx#combine-when-with-and-or-and-not)
+ * [Parameter and null handling](../../../querying/filtering-query-results/conditional-filtering.mdx#parameter-and-null-handling)
+ * [Type handling](../../../querying/filtering-query-results/conditional-filtering.mdx#type-handling)
+ * [Logical expressions in the condition](../../../querying/filtering-query-results/conditional-filtering.mdx#logical-expressions-in-the-condition)
+ * [Using `in` and `all in` in the condition](../../../querying/filtering-query-results/conditional-filtering.mdx#using-in-and-all-in-in-the-condition)
+ * [Restrictions](../../../querying/filtering-query-results/conditional-filtering.mdx#restrictions)
+ * [Syntax](../../../querying/filtering-query-results/conditional-filtering.mdx#syntax)
+
+
+
+
+
+* Use conditional filtering when one query needs to support several **optional** search criteria,
+ such as title, country, status, or date range.
+
+* **Without `when`**, the client often builds the RQL dynamically, adding predicates only for parameters that were supplied.
+ Doing so creates many query-text variations and makes the query harder to read, test, and maintain.
+
+* **With `when`**, the client can pass all optional values as query parameters and keep one stable RQL query.
+ Each optional predicate is applied only when its corresponding condition is `true`.
+
+* Conditional filtering is useful when missing or `null` parameters should simply skip the specified predicate,
+ rather than require a different query string.
+
+
+
+
+
+* The following query searches employees and conditionally applies two predicates:
+ one for _title_ and one for _country_.
+
+* The values are passed as query parameters.
+ In RQL, `$title` uses the value passed by `.AddParameter("title", title)`,
+ and `$country` uses the value passed by `.AddParameter("country", country)`.
+
+* The query text stays the same for every request. Only the parameter values change.
+
+
+
+ ```csharp
+ string? title = "Sales Representative"; // Use null to skip the title predicate.
+ string? country = "USA"; // Use null to skip the country predicate.
+
+ List employees = session.Advanced
+ .RawQuery(@"
+ from Employees
+ where when($title != null, Title == $title)
+ and when($country != null, Address.Country == $country)")
+ .AddParameter("title", title)
+ .AddParameter("country", country)
+ .ToList();
+ ```
+
+
+ ```csharp
+ string? title = "Sales Representative"; // Use null to skip the title predicate.
+ string? country = "USA"; // Use null to skip the country predicate.
+
+ List employees = await asyncSession.Advanced
+ .AsyncRawQuery(@"
+ from Employees
+ where when($title != null, Title == $title)
+ and when($country != null, Address.Country == $country)")
+ .AddParameter("title", title)
+ .AddParameter("country", country)
+ .ToListAsync();
+ ```
+
+
+ ```sql
+ from Employees
+ where when($title != null, Title == $title)
+ and when($country != null, Address.Country == $country)
+
+ { "title": "Sales Representative", "country": "USA" }
+ ```
+
+
+
+* **When both parameters are non-null**, both predicates are applied and the query behaves like:
+
+ ```sql
+ from Employees
+ where Title == $title and Address.Country == $country
+ ```
+
+* **When only `$country` is non-null**, the _title_ predicate is skipped and the query behaves like:
+
+ ```sql
+ from Employees
+ where Address.Country == $country
+ ```
+
+* **When only `$title` is non-null**, the _country_ predicate is skipped and the query behaves like:
+
+ ```sql
+ from Employees
+ where Title == $title
+ ```
+
+* **When both parameters are `null` or missing**,
+ both conditional predicates are skipped and the query returns all employees, i.e.:
+
+ ```sql
+ from Employees
+ ```
+
+
+
+
+
+* A `when` clause can be combined with standard `and`, `or`, and `not` operators.
+
+* **When the condition is `true`** -
+ the predicate inside `when` participates in the surrounding boolean expression.
+
+ **When the condition is `false`** -
+ that predicate is skipped.
+
+* The following table summarizes the resulting behavior:
+
+ | Expression | When condition is true | When condition is false |
+ |--------------------------------------------------|---------------------------------|---------------------------|
+ | `when(condition, Predicate1) and Predicate2` | `Predicate1 and Predicate2` | `Predicate2` |
+ | `when(condition, Predicate1) or Predicate2` | `Predicate1 or Predicate2` | `Predicate2` |
+ | `when(condition, Predicate1) and not Predicate2` | `Predicate1 and not Predicate2` | `not Predicate2` |
+ | `Predicate2 and not when(condition, Predicate1)` | `Predicate2 and not Predicate1` | `Predicate2` |
+
+* **If every predicate in the `where` clause is skipped** -
+ the query behaves as if it has no `where` clause and returns all documents from the queried collection or index.
+
+* **Example** - combine optional search criteria with a required predicate using `and`:
+
+
+
+ ```csharp
+ List products = session.Advanced
+ .RawQuery(@"
+ from Products
+ where when($onlyInStock == true, UnitsInStock > 0)
+ and Discontinued == false")
+ .AddParameter("onlyInStock", true)
+ .ToList();
+ ```
+
+
+ ```csharp
+ List products = await asyncSession.Advanced
+ .AsyncRawQuery(@"
+ from Products
+ where when($onlyInStock == true, UnitsInStock > 0)
+ and Discontinued == false")
+ .AddParameter("onlyInStock", true)
+ .ToListAsync();
+ ```
+
+
+ ```sql
+ from Products
+ where when($onlyInStock == true, UnitsInStock > 0)
+ and Discontinued == false
+
+ { "onlyInStock": true }
+ ```
+
+
+
+ * When `$onlyInStock` is `true`:
+ the `UnitsInStock > 0` predicate is applied, so the query returns non-discontinued products that are in stock.
+
+ * When `$onlyInStock` is `false`:
+ the `UnitsInStock > 0` predicate is skipped, so the query returns all non-discontinued products.
+
+
+
+
+
+* The condition compares **query parameters** (e.g. `$title`, `$country`) against literal values.
+ The left-hand side of each comparison must be a parameter reference (a `$`-prefixed name).
+
+* **Missing parameters are treated as `null`.**
+ A parameter that was never supplied behaves exactly like a parameter explicitly set to `null`.
+
+* You can test for parameters that are `null` or missing with `== null` and `!= null`:
+
+ ```sql
+ // Apply the Title predicate only when $title is non-null:
+ from Employees
+ where when($title != null, Title == $title)
+
+ // Apply a "no title set" predicate only when $title is null or missing:
+ from Employees
+ where when($title == null, Title == null)
+ ```
+
+* When a parameter is `null` (or missing) and it is compared against a **non-null** value,
+ only `!=` evaluates to `true`; all other operators evaluate to `false`.
+ For example, if `$p` is missing: `$p != 5` is `true`, while `$p == 5`, `$p > 5`, etc. are all `false`.
+
+
+
+
+
+* Comparisons are evaluated based on the type of the literal value being compared against,
+ and the parameter value is converted to match when a sensible conversion exists.
+ When no such conversion exists, the query fails with `RavenException`.
+
+* **Comparing against a number literal**:
+ When comparing against a number literal, RavenDB converts between `Long` and `Double`
+ (1 and 1.0 compare as equal), and all operators (`==`, `!=`, `<`, `<=`, `>`, `>=`) are supported.
+ A string parameter that holds a numeric value (e.g. "10") is parsed and compared as a number.
+ A parameter that cannot be converted to a number (a non-numeric string or a boolean) throws `RavenException`.
+
+ ```sql
+ // Valid - RavenDB converts between Long and Double:
+ where when($longParam >= 10, ...)
+
+ // Valid - a numeric string parameter is compared as a number:
+ where when($numericStringParam == 10, ...)
+ ```
+
+* **Comparing against a string literal**:
+ When comparing against a string literal, the parameter must be a string.
+ A number or boolean parameter compared against a string literal throws `RavenException`.
+ String value comparisons are case-insensitive (ordinal, ignore-case).
+
+ ```sql
+ // Valid - strings compare case-insensitively:
+ where when($stringParam == 'active', ...)
+
+ // Throws RavenException -
+ // string literal requires comparing against a string param
+ where when($numberParam == 'ten', ...)
+ ```
+
+* **Comparing against a boolean literal**:
+ When comparing against a boolean literal, only the equality operators `==` and `!=` are supported.
+ Using an inequality operator (`<`, `<=`, `>`, `>=`) throws `RavenException`.
+ The parameter must also be a boolean; a non-boolean parameter throws `RavenException`.
+
+ ```sql
+ // Valid - booleans with == / !=:
+ where when($booleanParam == false, ...)
+
+ // Throws RavenException - inequality on a boolean:
+ where when($booleanParam > false, ...)
+ ```
+
+* **Comparing against `null`**:
+ A parameter is `null` if it is explicitly `null` or not supplied.
+
+ When comparing against a `null` literal, only `==` and `!=` are supported (other operators return `false`):
+ `$param == null` matches a null/missing parameter;
+ `$param != null` matches any non-null value.
+
+ When comparing against a **non-null** literal, a null/missing parameter makes `!=` return `true`
+ and every other operator (including `==`) return `false` - it never raises a type error.
+
+
+
+
+
+* The condition can combine several parameter checks with `and`, `or`, `not`, and parentheses.
+ Use parentheses to make the intended grouping explicit.
+
+
+
+ ```csharp
+ List employees = session.Advanced
+ .RawQuery(@"
+ from Employees
+ where when(($title == 'Sales Representative' or $title == 'Sales Manager')
+ and not ($includeAllTitles == true),
+ Title == $title)")
+ .AddParameter("title", "Sales Representative")
+ .AddParameter("includeAllTitles", false)
+ .ToList();
+ ```
+
+
+ ```csharp
+ List employees = await asyncSession.Advanced
+ .AsyncRawQuery(@"
+ from Employees
+ where when(($title == 'Sales Representative' or $title == 'Sales Manager')
+ and not ($includeAllTitles == true),
+ Title == $title)")
+ .AddParameter("title", "Sales Representative")
+ .AddParameter("includeAllTitles", false)
+ .ToListAsync();
+ ```
+
+
+ ```sql
+ from Employees
+ where when(($title == 'Sales Representative' or $title == 'Sales Manager')
+ and not ($includeAllTitles == true),
+ Title == $title)
+
+ { "title": "Sales Representative", "includeAllTitles": false }
+ ```
+
+
+
+ * When `$title` is `"Sales Representative"` OR `"Sales Manager"` AND `$includeAllTitles` is `false`:
+ the `Title == $title` predicate is **applied**.
+
+ * When `$includeAllTitles` is `true`, OR `$title` has another value:
+ the `Title == $title` predicate is **skipped**.
+
+
+
+
+
+* The condition can also use `in` and `all in` to test a parameter against a set of values.
+
+* **`in`** -
+ the condition is `true` when the parameter value matches **any** of the listed values.
+ When the parameter is an array, the condition is `true` when the array shares **at least one** value with the list.
+
+* **`all in`** -
+ when the parameter is an array, the condition is `true` only when **every** value
+ in the parameter array is contained in the listed values.
+
+* **Example** - apply an in-stock predicate only when the requested categories include `"Beverages"` or `"Condiments"`:
+
+
+
+ ```csharp
+ List products = session.Advanced
+ .RawQuery(@"
+ from Products
+ where when($categories in ('Beverages', 'Condiments'),
+ UnitsInStock > 0)")
+ .AddParameter("categories", new[] { "Beverages", "Seafood" })
+ .ToList();
+ ```
+
+
+ ```csharp
+ List products = await asyncSession.Advanced
+ .AsyncRawQuery(@"
+ from Products
+ where when($categories in ('Beverages', 'Condiments'),
+ UnitsInStock > 0)")
+ .AddParameter("categories", new[] { "Beverages", "Seafood" })
+ .ToListAsync();
+ ```
+
+
+ ```sql
+ from Products
+ where when($categories in ('Beverages', 'Condiments'),
+ UnitsInStock > 0)
+
+ { "categories": ["Beverages", "Seafood"] }
+ ```
+
+
+
+ * When `$categories` contains `"Beverages"` or `"Condiments"`:
+ the `UnitsInStock > 0` predicate is **applied**.
+
+ * Otherwise:
+ the `UnitsInStock > 0` predicate is **skipped**, and all products are returned.
+
+* As with scalar string comparisons, string value matching in `in` and `all in` conditions is **case-insensitive**.
+
+* `in` and `all in` compare formatted string values, so some mixed parameter and list value types can match.
+ For example, a parameter value of `"1"` can match `in (1, 2, 3)`,
+ and a parameter value of `1` can match `in ('1', '2', '3')`.
+
+ The comparison is textual: each value is formatted as a string before comparison.
+ Values that are numerically equal but have different string representations,
+ such as the string `"1.0"` and the number `1` (formatted as `"1"`), are not considered a match.
+
+
+
+
+
+* **A `when` condition cannot contain another `when`**
+ The condition (the first argument) of `when(condition, predicate)` cannot include another `when(...)` call.
+ Attempting to use `when` inside the condition, for example, `when(when($b == 2, Number == 2), Number == 1)`, raises a parse error.
+
+* **The condition operates on parameters, not document fields**
+ The left-hand side of each comparison in the condition must be a query parameter (a `$`-prefixed name).
+ The condition is evaluated once, at query-planning time, against the supplied parameters - it does not inspect document data.
+ Document matching is done by the second argument, the predicate.
+
+* **AI agent parameter names**
+ When the query is issued by an [AI agent](../../../ai-integration/ai-agents/overview.mdx),
+ parameter names in the condition are **case-sensitive**.
+ This applies to parameter names only; string comparisons remain case-insensitive.
+
+
+
+
+
+
+
+```sql
+when(, )
+```
+
+
+
+| Parameter | Description |
+|-----------------|-------------|
+| **condition** | A boolean expression evaluated server-side against **query parameters**.
Each comparison has the form `$param value`.
Supports `==`, `!=`, `<`, `<=`, `>`, `>=`, `in`, `all in`, combined with `and`, `or`, `not`, and parentheses. |
+| **predicate** | A regular query predicate, matched against the **documents**.
Applied when `condition` is `true`; skipped when `condition` is `false`. |
+
+---
+
+* The function name is **case-insensitive** in RQL:
+ `when(...)` and `WHEN(...)` are equivalent.
+
+* **Operator support per type**:
+
+ | Type | Supported operators | Notes |
+ |---------|--------------------------------------------------|-------|
+ | Number | `==`, `!=`, `<`, `<=`, `>`, `>=`, `in`, `all in` | RavenDB converts between `Long` and `Double` (`1 == 1.0`). |
+ | String | `==`, `!=`, `<`, `<=`, `>`, `>=`, `in`, `all in` | String value matching is **case-insensitive**
(ordinal, ignore-case). |
+ | Boolean | `==`, `!=` | Using inequality operators throws a `RavenException`. |
+ | Null | `== null`, `!= null` | A missing parameter is treated as `null`. |
+
+