From 528fdb35e9294fd3af6092e60d44c337692a184a Mon Sep 17 00:00:00 2001 From: Danielle9897 Date: Wed, 10 Jun 2026 14:57:14 +0300 Subject: [PATCH 1/3] RDoc-3902 RDoc-3902 The "use logical operators" article (C#) --- .../content/_use-logical-operators-csharp.mdx | 672 ++++++++++++++++++ .../filter-by-date-and-time.mdx | 2 +- .../use-logical-operators.mdx | 31 + 3 files changed, 704 insertions(+), 1 deletion(-) create mode 100644 docs/querying/filtering-query-results/content/_use-logical-operators-csharp.mdx create mode 100644 docs/querying/filtering-query-results/use-logical-operators.mdx diff --git a/docs/querying/filtering-query-results/content/_use-logical-operators-csharp.mdx b/docs/querying/filtering-query-results/content/_use-logical-operators-csharp.mdx new file mode 100644 index 0000000000..9e5bca14d9 --- /dev/null +++ b/docs/querying/filtering-query-results/content/_use-logical-operators-csharp.mdx @@ -0,0 +1,672 @@ +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'; + + + +* A query's `where` clause can combine multiple filtering conditions with logical operators. + This lets you express richer predicates than a single condition, for example: + _"products that are in stock **and** cost more than 50"_, or _"employees whose first name is Robert **or** Nancy"_. + +* This article covers the logical operators available when filtering query results: + **AND**, **OR**, and **NOT**, as well as how to **group conditions** to control operator precedence. + The examples are shown with: + * **Query** + the LINQ-based query API, using C# operators such as `&&`, `||`, `!`, and `!=`. + * **DocumentQuery** + the low-level query API, using methods and modifiers such as `AndAlso`, `OrElse`, `Not`, and `WhereNotEquals`. + * **RawQuery** + the client API for executing an RQL string directly, with query parameters supplied by `AddParameter`. + * **RQL** + the raw query language, using `and`, `or`, `not (...)`, and comparison operators such as `!=`. + RQL keywords are case-insensitive; the examples below use lowercase. + +* The same logical-operator rules apply when querying a collection dynamically + and when [querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index). + +* For filtering by field value, numeric value, nested field, collection, document ID, and other basic conditions, + see [Filter query results](../../../querying/filtering-query-results/filter-query-results.mdx). + +--- + +* In this article: + * [Combine conditions with AND](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-and) + * [Combine conditions with OR](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-or) + * [Negate a condition with NOT](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) + * [Negate a group of conditions](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-group-of-conditions) + * [Group conditions to control precedence](../../../querying/filtering-query-results/use-logical-operators.mdx#group-conditions-to-control-precedence) + * [Logical operators when querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index) + * [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults) + + + + + +Use the **AND** operator to return only documents that satisfy **all** conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is `"Robert"` **and** `LastName` is `"King"`. + + + +```csharp +List employees = session + .Query() + .Where(e => e.FirstName == "Robert" && e.LastName == "King") + .ToList(); +``` + + +```csharp +List employees = await asyncSession + .Query() + .Where(e => e.FirstName == "Robert" && e.LastName == "King") + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .DocumentQuery() + .WhereEquals(e => e.FirstName, "Robert") + .AndAlso() // Combine the two predicates with 'AndAlso' + .WhereEquals(e => e.LastName, "King") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncDocumentQuery() + .WhereEquals(e => e.FirstName, "Robert") + .AndAlso() // Combine the two predicates with 'AndAlso' + .WhereEquals(e => e.LastName, "King") + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .RawQuery("from Employees where FirstName = $firstName and LastName = $lastName") + .AddParameter("firstName", "Robert") + .AddParameter("lastName", "King") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncRawQuery( + "from Employees where FirstName = $firstName and LastName = $lastName") + .AddParameter("firstName", "Robert") + .AddParameter("lastName", "King") + .ToListAsync(); +``` + + +```sql +from Employees +where FirstName = "Robert" and LastName = "King" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName` +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Chaining conditions uses AND + +* In a **LINQ query**, chaining multiple `Where` calls combines the conditions with AND. + For example: + `.Where(e => e.FirstName == "Robert").Where(e => e.LastName == "King")` + is equivalent to: + `.Where(e => e.FirstName == "Robert" && e.LastName == "King")`. + +* In a **DocumentQuery**, consecutive `Where*` predicates are also combined with AND by default. + For example: + `.WhereEquals(e => e.FirstName, "Robert").WhereEquals(e => e.LastName, "King")` + is equivalent to: + `.WhereEquals(e => e.FirstName, "Robert").AndAlso().WhereEquals(e => e.LastName, "King")`. + + + + + + + +Use the **OR** operator to return documents that satisfy **at least one** of the specified conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```csharp +List employees = session + .Query() + .Where(e => e.FirstName == "Robert" || e.FirstName == "Nancy") + .ToList(); +``` + + +```csharp +List employees = await asyncSession + .Query() + .Where(e => e.FirstName == "Robert" || e.FirstName == "Nancy") + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .DocumentQuery() + .WhereEquals(e => e.FirstName, "Robert") + .OrElse() // Combine the two predicates with 'OrElse' + .WhereEquals(e => e.FirstName, "Nancy") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncDocumentQuery() + .WhereEquals(e => e.FirstName, "Robert") + .OrElse() // Combine the two predicates with 'OrElse' + .WhereEquals(e => e.FirstName, "Nancy") + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .RawQuery( + "from Employees where FirstName = $firstName1 or FirstName = $firstName2") + .AddParameter("firstName1", "Robert") + .AddParameter("firstName2", "Nancy") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncRawQuery( + "from Employees where FirstName = $firstName1 or FirstName = $firstName2") + .AddParameter("firstName1", "Robert") + .AddParameter("firstName2", "Nancy") + .ToListAsync(); +``` + + +```sql +from Employees +where FirstName = "Robert" or FirstName = "Nancy" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Use IN for multiple values on the same field + +When the same field is compared against multiple possible values, as in the example above, +you can use `In` / `WhereIn` instead of repeating OR conditions. +See [Filter by multiple possible values](../../../querying/filtering-query-results/filter-query-results.mdx#filter-by-multiple-possible-values). + + + + + + + +Use the **NOT** operator to return only documents that do **not** satisfy the specified condition. + +For example, the following query returns _Employee_ documents where `FirstName` is **not** `"Robert"`. + + + +```csharp +List employees = session + .Query() + .Where(e => e.FirstName != "Robert") + .ToList(); +``` + + +```csharp +List employees = await asyncSession + .Query() + .Where(e => e.FirstName != "Robert") + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .DocumentQuery() + .Not // Negate the next predicate + .WhereEquals(e => e.FirstName, "Robert") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncDocumentQuery() + .Not // Negate the next predicate + .WhereEquals(e => e.FirstName, "Robert") + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .RawQuery("from Employees where FirstName != $firstName") + .AddParameter("firstName", "Robert") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncRawQuery("from Employees where FirstName != $firstName") + .AddParameter("firstName", "Robert") + .ToListAsync(); +``` + + +```sql +from Employees +where FirstName != "Robert" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Using WhereNotEquals with DocumentQuery + +* In a _DocumentQuery_, the `Not` operator negates only the next predicate or subclause. + It cannot be used on its own; it must be followed by a predicate or by `OpenSubclause()`. + +* For a single equality condition, you can use `WhereNotEquals` instead of `Not.WhereEquals`. + For example: + ```csharp + List employees = session.Advanced + .DocumentQuery() + .WhereNotEquals(e => e.FirstName, "Robert") + .ToList(); + ``` + is equivalent to: + ```csharp + List employees = session.Advanced + .DocumentQuery() + .Not + .WhereEquals(e => e.FirstName, "Robert") + .ToList(); + ``` + + + + + + + +Use **NOT** with grouping to negate multiple conditions as a single unit. + +For example, the following query returns _Employee_ documents that are **not** +(`FirstName` is `"Robert"` **and** `LastName` is `"King"`). + +In a _DocumentQuery_, place `Not` before `OpenSubclause()` to negate the whole group. + + + +```csharp +List employees = session + .Query() + .Where(e => !(e.FirstName == "Robert" && e.LastName == "King")) + .ToList(); +``` + + +```csharp +List employees = await asyncSession + .Query() + .Where(e => !(e.FirstName == "Robert" && e.LastName == "King")) + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .DocumentQuery() + .Not // Negate the whole group that follows + .OpenSubclause() // Open the group + .WhereEquals(e => e.FirstName, "Robert") + .AndAlso() + .WhereEquals(e => e.LastName, "King") + .CloseSubclause() // Close the group + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncDocumentQuery() + .Not // Negate the whole group that follows + .OpenSubclause() // Open the group + .WhereEquals(e => e.FirstName, "Robert") + .AndAlso() + .WhereEquals(e => e.LastName, "King") + .CloseSubclause() // Close the group + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .RawQuery( + "from Employees where true and not (FirstName = $firstName and LastName = $lastName)") + .AddParameter("firstName", "Robert") + .AddParameter("lastName", "King") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncRawQuery( + "from Employees where true and not (FirstName = $firstName and LastName = $lastName)") + .AddParameter("firstName", "Robert") + .AddParameter("lastName", "King") + .ToListAsync(); +``` + + +```sql +from Employees +where true and not (FirstName = "Robert" and LastName = "King") + +// In RQL, NOT cannot start a where clause; it must follow a valid preceding expression. +// Use true and not (...) when the whole where clause starts with a negated group. +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName` +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Alternative syntax + +* `not (A and B)` is equivalent to `not A or not B`. + For example, the query above: + `not (FirstName = "Robert" and LastName = "King")` + can also be expressed as: + `FirstName != "Robert" or LastName != "King"`. + +* In a **DocumentQuery**, this is: + `WhereNotEquals(e => e.FirstName, "Robert").OrElse().WhereNotEquals(e => e.LastName, "King")`. + +* In **RQL**, this is: + `from Employees where FirstName != "Robert" or LastName != "King"`. + + + + + + + +When you mix **AND** and **OR** in the same query, use grouping to control which conditions are evaluated together. +In a _DocumentQuery_, group conditions with `OpenSubclause()` and `CloseSubclause()`; +in a _LINQ_ query and in _RQL_, use parentheses. + +For example, the following query returns _Employee_ documents whose `Title` is `"Sales Representative"` +**and** whose `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```csharp +List employees = session + .Query() + .Where(e => e.Title == "Sales Representative" && + (e.FirstName == "Robert" || e.FirstName == "Nancy")) + .ToList(); +``` + + +```csharp +List employees = await asyncSession + .Query() + .Where(e => e.Title == "Sales Representative" && + (e.FirstName == "Robert" || e.FirstName == "Nancy")) + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .DocumentQuery() + .WhereEquals(e => e.Title, "Sales Representative") + .AndAlso() + .OpenSubclause() // Group the OR conditions so they are evaluated together + .WhereEquals(e => e.FirstName, "Robert") + .OrElse() + .WhereEquals(e => e.FirstName, "Nancy") + .CloseSubclause() + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncDocumentQuery() + .WhereEquals(e => e.Title, "Sales Representative") + .AndAlso() + .OpenSubclause() // Group the OR conditions so they are evaluated together + .WhereEquals(e => e.FirstName, "Robert") + .OrElse() + .WhereEquals(e => e.FirstName, "Nancy") + .CloseSubclause() + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .RawQuery( + "from Employees where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .AddParameter("title", "Sales Representative") + .AddParameter("firstName1", "Robert") + .AddParameter("firstName2", "Nancy") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncRawQuery( + "from Employees where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .AddParameter("title", "Sales Representative") + .AddParameter("firstName1", "Robert") + .AddParameter("firstName2", "Nancy") + .ToListAsync(); +``` + + +```sql +from Employees +where Title = "Sales Representative" and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndTitle` +> The auto-index is derived from the _Title_ and _FirstName_ fields referenced in the _where_ clause. + +--- + + + +#### Grouping matters + +Without the grouping, the query: +`Title = "Sales Representative" and FirstName = "Robert" or FirstName = "Nancy"` +is evaluated as: +`(Title = "Sales Representative" and FirstName = "Robert") or FirstName = "Nancy"`, +because **AND** has higher precedence than **OR** (see [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults)). +This returns a different set of documents than the grouped query. + + + + + + + +The logical operators work the same way when querying a static index. +The conditions in the `where` clause are evaluated against the index-fields. + +For example, if a static index defines `FirstName`, `LastName`, and `Title` fields, +you can combine conditions on those fields just as you would in a dynamic query: + + + +```csharp +public class Employees_ByNameAndTitle : AbstractIndexCreationTask +{ + public class IndexEntry + { + // The index fields + public string FirstName { get; set; } + public string LastName { get; set; } + public string Title { get; set; } + } + + public Employees_ByNameAndTitle() + { + Map = employees => from employee in employees + select new IndexEntry + { + FirstName = employee.FirstName, + LastName = employee.LastName, + Title = employee.Title + }; + } +} +``` + + +```csharp +List employees = session + .Query() + .Where(e => e.Title == "Sales Representative" && + (e.FirstName == "Robert" || e.FirstName == "Nancy")) + .ToList(); +``` + + +```csharp +List employees = await asyncSession + .Query() + .Where(e => e.Title == "Sales Representative" && + (e.FirstName == "Robert" || e.FirstName == "Nancy")) + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .DocumentQuery() + .WhereEquals(e => e.Title, "Sales Representative") + .AndAlso() + .OpenSubclause() + .WhereEquals(e => e.FirstName, "Robert") + .OrElse() + .WhereEquals(e => e.FirstName, "Nancy") + .CloseSubclause() + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncDocumentQuery() + .WhereEquals(e => e.Title, "Sales Representative") + .AndAlso() + .OpenSubclause() + .WhereEquals(e => e.FirstName, "Robert") + .OrElse() + .WhereEquals(e => e.FirstName, "Nancy") + .CloseSubclause() + .ToListAsync(); +``` + + +```csharp +List employees = session.Advanced + .RawQuery( + "from index 'Employees/ByNameAndTitle' " + + "where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .AddParameter("title", "Sales Representative") + .AddParameter("firstName1", "Robert") + .AddParameter("firstName2", "Nancy") + .ToList(); +``` + + +```csharp +List employees = await asyncSession.Advanced + .AsyncRawQuery( + "from index 'Employees/ByNameAndTitle' " + + "where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .AddParameter("title", "Sales Representative") + .AddParameter("firstName1", "Robert") + .AddParameter("firstName2", "Nancy") + .ToListAsync(); +``` + + +```sql +from index "Employees/ByNameAndTitle" +where Title = "Sales Representative" + and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + + + + + +* **Precedence:** + When AND and OR appear together without grouping, **AND is evaluated before OR**. + In other words, `a and b or c` is interpreted as `(a and b) or c`. + Use grouping (`OpenSubclause` / `CloseSubclause` or parentheses) whenever you need a different evaluation order. + +* **Default operator in DocumentQuery:** + When consecutive `Where*` predicates in a **DocumentQuery** are written without an explicit + `AndAlso` or `OrElse` between them, they are combined with **AND** by default. + Use `AndAlso` to make the implicit AND explicit, or `OrElse` when you need OR. + +* **NOT requires a following predicate or subclause:** + The `Not` operator negates the predicate or subclause that comes immediately after it. + It cannot be used on its own. + + \ No newline at end of file diff --git a/docs/querying/filtering-query-results/filter-by-date-and-time.mdx b/docs/querying/filtering-query-results/filter-by-date-and-time.mdx index 42ec9b8744..c2bfbff63c 100644 --- a/docs/querying/filtering-query-results/filter-by-date-and-time.mdx +++ b/docs/querying/filtering-query-results/filter-by-date-and-time.mdx @@ -2,7 +2,7 @@ title: "Filter by Date and Time" sidebar_label: "Filter by Date and Time" description: "Learn how to filter RavenDB query results by date and time using explicit UTC date-time values, now(), today(), and time offsets, including supported syntax, restrictions, and query caching behavior." -sidebar_position: 1 +sidebar_position: 3 supported_languages: ["csharp"] see_also: - title: "Query Overview" diff --git a/docs/querying/filtering-query-results/use-logical-operators.mdx b/docs/querying/filtering-query-results/use-logical-operators.mdx new file mode 100644 index 0000000000..cbee392022 --- /dev/null +++ b/docs/querying/filtering-query-results/use-logical-operators.mdx @@ -0,0 +1,31 @@ +--- +title: "Use Logical Operators" +sidebar_label: "Use Logical Operators" +description: "Learn how to combine multiple filtering conditions in a query using the logical operators AND, OR, and NOT, and how to group conditions to control their evaluation order." +sidebar_position: 2 +supported_languages: ["csharp"] +see_also: + - title: "Filter Query Results" + link: "querying/filtering-query-results/filter-query-results" + source: "docs" + path: "Querying > Filtering Query Results" + - title: "Conditional Filtering" + link: "querying/filtering-query-results/conditional-filtering" + source: "docs" + path: "Querying > Filtering Query Results" + - title: "Query Overview" + link: "querying/overview" + source: "docs" + path: "Querying" +--- + +import LanguageSwitcher from "@site/src/components/LanguageSwitcher"; +import LanguageContent from "@site/src/components/LanguageContent"; + +import UseLogicalOperatorsCsharp from './content/_use-logical-operators-csharp.mdx'; + + + + + + From 289bb5a3d3658cefe0647fc1487da2ba67b8ed1e Mon Sep 17 00:00:00 2001 From: Danielle9897 Date: Thu, 11 Jun 2026 13:25:54 +0300 Subject: [PATCH 2/3] RDoc-3902 The "use logical operators" article (node.js, php, python, java) --- .../content/_use-logical-operators-java.mdx | 422 +++++++++++++++++ .../content/_use-logical-operators-nodejs.mdx | 424 +++++++++++++++++ .../content/_use-logical-operators-php.mdx | 424 +++++++++++++++++ .../content/_use-logical-operators-python.mdx | 428 ++++++++++++++++++ 4 files changed, 1698 insertions(+) create mode 100644 docs/querying/filtering-query-results/content/_use-logical-operators-java.mdx create mode 100644 docs/querying/filtering-query-results/content/_use-logical-operators-nodejs.mdx create mode 100644 docs/querying/filtering-query-results/content/_use-logical-operators-php.mdx create mode 100644 docs/querying/filtering-query-results/content/_use-logical-operators-python.mdx diff --git a/docs/querying/filtering-query-results/content/_use-logical-operators-java.mdx b/docs/querying/filtering-query-results/content/_use-logical-operators-java.mdx new file mode 100644 index 0000000000..f7204770be --- /dev/null +++ b/docs/querying/filtering-query-results/content/_use-logical-operators-java.mdx @@ -0,0 +1,422 @@ +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'; + + + +* A query's `where` clause can combine multiple filtering conditions with logical operators. + This lets you express richer predicates than a single condition, for example: + _"products that are in stock **and** cost more than 50"_, or _"employees whose first name is Robert **or** Nancy"_. + +* This article covers the logical operators available when filtering query results: + **AND**, **OR**, and **NOT**, as well as how to **group conditions** to control operator precedence. + The examples are shown with: + * **Query** + the high-level query API (`session.query`), using methods such as `whereEquals`, `whereNotEquals`, `andAlso`, `orElse`, and `not()`. + * **RawQuery** + the client API for executing an RQL string directly, with query parameters supplied by `addParameter`. + * **RQL** + the raw query language, using `and`, `or`, `not (...)`, and comparison operators such as `!=`. + RQL keywords are case-insensitive; the examples below use lowercase. + +* The same logical-operator rules apply when querying a collection dynamically + and when [querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index). + +* For filtering by field value, numeric value, nested field, collection, document ID, and other basic conditions, + see [Filter query results](../../../querying/filtering-query-results/filter-query-results.mdx). + +--- + +* In this article: + * [Combine conditions with AND](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-and) + * [Combine conditions with OR](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-or) + * [Negate a condition with NOT](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) + * [Negate a group of conditions](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-group-of-conditions) + * [Group conditions to control precedence](../../../querying/filtering-query-results/use-logical-operators.mdx#group-conditions-to-control-precedence) + * [Logical operators when querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index) + * [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults) + + + + + +Use the **AND** operator to return only documents that satisfy **all** conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is `"Robert"` **and** `LastName` is `"King"`. + + + +```java +List employees = session + .query(Employee.class) + .whereEquals("FirstName", "Robert") + .andAlso() // Combine the two predicates with 'andAlso' + .whereEquals("LastName", "King") + .toList(); +``` + + +```java +List employees = session.advanced() + .rawQuery(Employee.class, + "from Employees where FirstName = $firstName and LastName = $lastName") + .addParameter("firstName", "Robert") + .addParameter("lastName", "King") + .toList(); +``` + + +```sql +from Employees +where FirstName = "Robert" and LastName = "King" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName`. +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Chaining conditions uses AND + +Consecutive `where*` predicates are combined with AND by default. +For example: +`.whereEquals("FirstName", "Robert").whereEquals("LastName", "King")` +is equivalent to: +`.whereEquals("FirstName", "Robert").andAlso().whereEquals("LastName", "King")`. + + + + + + + +Use the **OR** operator to return documents that satisfy **at least one** of the specified conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```java +List employees = session + .query(Employee.class) + .whereEquals("FirstName", "Robert") + .orElse() // Combine the two predicates with 'orElse' + .whereEquals("FirstName", "Nancy") + .toList(); +``` + + +```java +List employees = session.advanced() + .rawQuery(Employee.class, + "from Employees where FirstName = $firstName1 or FirstName = $firstName2") + .addParameter("firstName1", "Robert") + .addParameter("firstName2", "Nancy") + .toList(); +``` + + +```sql +from Employees +where FirstName = "Robert" or FirstName = "Nancy" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Use IN for multiple values on the same field + +When the same field is compared against multiple possible values, as in the example above, +you can use `whereIn` instead of repeating OR conditions. +See [Filter by multiple possible values](../../../querying/filtering-query-results/filter-query-results.mdx#filter-by-multiple-possible-values). + + + + + + + +Use the **NOT** operator to return only documents that do **not** satisfy the specified condition. + +For example, the following query returns _Employee_ documents where `FirstName` is **not** `"Robert"`. + + + +```java +List employees = session + .query(Employee.class) + .not() // Negate the next predicate + .whereEquals("FirstName", "Robert") + .toList(); +``` + + +```java +List employees = session.advanced() + .rawQuery(Employee.class, "from Employees where FirstName != $firstName") + .addParameter("firstName", "Robert") + .toList(); +``` + + +```sql +from Employees +where FirstName != "Robert" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Using whereNotEquals + +* The `not()` operator negates only the next predicate or subclause. + It cannot be used on its own; it must be followed by a predicate or by `openSubclause()`. + +* For a single equality condition, you can use `whereNotEquals` instead of `not().whereEquals`. + For example: + ```java + List employees = session + .query(Employee.class) + .whereNotEquals("FirstName", "Robert") + .toList(); + ``` + is equivalent to: + ```java + List employees = session + .query(Employee.class) + .not() + .whereEquals("FirstName", "Robert") + .toList(); + ``` + + + + + + + +Use **NOT** with grouping to negate multiple conditions as a single unit. + +For example, the following query returns _Employee_ documents that are **not** +(`FirstName` is `"Robert"` **and** `LastName` is `"King"`). + +In the query API, call `not()` before `openSubclause()` to negate the whole group. + + + +```java +List employees = session + .query(Employee.class) + .not() // Negate the whole group that follows + .openSubclause() // Open the group + .whereEquals("FirstName", "Robert") + .andAlso() + .whereEquals("LastName", "King") + .closeSubclause() // Close the group + .toList(); +``` + + +```java +List employees = session.advanced() + .rawQuery(Employee.class, + "from Employees where true and not (FirstName = $firstName and LastName = $lastName)") + .addParameter("firstName", "Robert") + .addParameter("lastName", "King") + .toList(); +``` + + +```sql +from Employees +where true and not (FirstName = "Robert" and LastName = "King") + +// In RQL, NOT cannot start a where clause; it must follow a valid preceding expression. +// Use true and not (...) when the whole where clause starts with a negated group. +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName` +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Alternative syntax + +* `not (A and B)` is equivalent to `not A or not B`. + For example, the query above: + `not (FirstName = "Robert" and LastName = "King")` + can also be expressed as: + `FirstName != "Robert" or LastName != "King"`. + +* In the query API, this is: + `.whereNotEquals("FirstName", "Robert").orElse().whereNotEquals("LastName", "King")`. + +* In **RQL**, this is: + `from Employees where FirstName != "Robert" or LastName != "King"`. + + + + + + + +When you mix **AND** and **OR** in the same query, use grouping to control which conditions are evaluated together. +In the query API, group conditions with `openSubclause()` and `closeSubclause()`; +in _RQL_, use parentheses. + +For example, the following query returns _Employee_ documents whose `Title` is `"Sales Representative"` +**and** whose `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```java +List employees = session + .query(Employee.class) + .whereEquals("Title", "Sales Representative") + .andAlso() + .openSubclause() // Group the OR conditions so they are evaluated together + .whereEquals("FirstName", "Robert") + .orElse() + .whereEquals("FirstName", "Nancy") + .closeSubclause() + .toList(); +``` + + +```java +List employees = session.advanced() + .rawQuery(Employee.class, + "from Employees where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .addParameter("title", "Sales Representative") + .addParameter("firstName1", "Robert") + .addParameter("firstName2", "Nancy") + .toList(); +``` + + +```sql +from Employees +where Title = "Sales Representative" and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndTitle` +> The auto-index is derived from the _Title_ and _FirstName_ fields referenced in the _where_ clause. + +--- + + + +#### Grouping matters + +Without the grouping, the query: +`Title = "Sales Representative" and FirstName = "Robert" or FirstName = "Nancy"` +is evaluated as: +`(Title = "Sales Representative" and FirstName = "Robert") or FirstName = "Nancy"`, +because **AND** has higher precedence than **OR** (see [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults)). +This returns a different set of documents than the grouped query. + + + + + + + +The logical operators work the same way when querying a static index. +The conditions in the `where` clause are evaluated against the index-fields. + +For example, if a static index defines `FirstName`, `LastName`, and `Title` fields, +you can combine conditions on those fields just as you would in a dynamic query: + + + +```java +public class Employees_ByNameAndTitle extends AbstractIndexCreationTask +{ + public Employees_ByNameAndTitle() + { + // The index fields are FirstName, LastName, and Title + map = "from employee in docs.Employees " + + "select new { employee.FirstName, employee.LastName, employee.Title }"; + } +} +``` + + +```java +List employees = session + .query(Employee.class, Employees_ByNameAndTitle.class) + .whereEquals("Title", "Sales Representative") + .andAlso() + .openSubclause() + .whereEquals("FirstName", "Robert") + .orElse() + .whereEquals("FirstName", "Nancy") + .closeSubclause() + .toList(); +``` + + +```java +List employees = session.advanced() + .rawQuery(Employee.class, + "from index 'Employees/ByNameAndTitle' " + + "where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .addParameter("title", "Sales Representative") + .addParameter("firstName1", "Robert") + .addParameter("firstName2", "Nancy") + .toList(); +``` + + +```sql +from index "Employees/ByNameAndTitle" +where Title = "Sales Representative" + and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + + + + + +* **Precedence:** + When AND and OR appear together without grouping, **AND is evaluated before OR**. + In other words, `a and b or c` is interpreted as `(a and b) or c`. + Use grouping (`openSubclause` / `closeSubclause` or parentheses) whenever you need a different evaluation order. + +* **Default operator:** + When consecutive `where*` predicates are written without an explicit + `andAlso` or `orElse` between them, they are combined with **AND** by default. + Use `andAlso` to make the implicit AND explicit, or `orElse` when you need OR. + +* **NOT requires a following predicate or subclause:** + The `not()` operator negates the predicate or subclause that comes immediately after it. + It cannot be used on its own. + + diff --git a/docs/querying/filtering-query-results/content/_use-logical-operators-nodejs.mdx b/docs/querying/filtering-query-results/content/_use-logical-operators-nodejs.mdx new file mode 100644 index 0000000000..b432028b6c --- /dev/null +++ b/docs/querying/filtering-query-results/content/_use-logical-operators-nodejs.mdx @@ -0,0 +1,424 @@ +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'; + + + +* A query's `where` clause can combine multiple filtering conditions with logical operators. + This lets you express richer predicates than a single condition, for example: + _"products that are in stock **and** cost more than 50"_, or _"employees whose first name is Robert **or** Nancy"_. + +* This article covers the logical operators available when filtering query results: + **AND**, **OR**, and **NOT**, as well as how to **group conditions** to control operator precedence. + The examples are shown with: + * **Query** + the high-level query API (`session.query`), using methods such as `whereEquals`, `whereNotEquals`, `andAlso`, `orElse`, and `not()`. + * **RawQuery** + the client API for executing an RQL string directly, with query parameters supplied by `addParameter`. + * **RQL** + the raw query language, using `and`, `or`, `not (...)`, and comparison operators such as `!=`. + RQL keywords are case-insensitive; the examples below use lowercase. + +* The same logical-operator rules apply when querying a collection dynamically + and when [querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index). + +* For filtering by field value, numeric value, nested field, collection, document ID, and other basic conditions, + see [Filter query results](../../../querying/filtering-query-results/filter-query-results.mdx). + +--- + +* In this article: + * [Combine conditions with AND](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-and) + * [Combine conditions with OR](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-or) + * [Negate a condition with NOT](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) + * [Negate a group of conditions](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-group-of-conditions) + * [Group conditions to control precedence](../../../querying/filtering-query-results/use-logical-operators.mdx#group-conditions-to-control-precedence) + * [Logical operators when querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index) + * [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults) + + + + + +Use the **AND** operator to return only documents that satisfy **all** conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is `"Robert"` **and** `LastName` is `"King"`. + + + +```javascript +const employees = await session + .query({ collection: "Employees" }) + .whereEquals("FirstName", "Robert") + .andAlso() // Combine the two predicates with 'andAlso' + .whereEquals("LastName", "King") + .all(); +``` + + +```javascript +const employees = await session.advanced + .rawQuery("from Employees where FirstName = $firstName and LastName = $lastName") + .addParameter("firstName", "Robert") + .addParameter("lastName", "King") + .all(); +``` + + +```sql +from Employees +where FirstName = "Robert" and LastName = "King" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName`. +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Chaining conditions uses AND + +Consecutive `where*` predicates are combined with AND by default. +For example: +`.whereEquals("FirstName", "Robert").whereEquals("LastName", "King")` +is equivalent to: +`.whereEquals("FirstName", "Robert").andAlso().whereEquals("LastName", "King")`. + + + + + + + +Use the **OR** operator to return documents that satisfy **at least one** of the specified conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```javascript +const employees = await session + .query({ collection: "Employees" }) + .whereEquals("FirstName", "Robert") + .orElse() // Combine the two predicates with 'orElse' + .whereEquals("FirstName", "Nancy") + .all(); +``` + + +```javascript +const employees = await session.advanced + .rawQuery("from Employees where FirstName = $firstName1 or FirstName = $firstName2") + .addParameter("firstName1", "Robert") + .addParameter("firstName2", "Nancy") + .all(); +``` + + +```sql +from Employees +where FirstName = "Robert" or FirstName = "Nancy" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Use IN for multiple values on the same field + +When the same field is compared against multiple possible values, as in the example above, +you can use `whereIn` instead of repeating OR conditions. +See [Filter by multiple possible values](../../../querying/filtering-query-results/filter-query-results.mdx#filter-by-multiple-possible-values). + + + + + + + +Use the **NOT** operator to return only documents that do **not** satisfy the specified condition. + +For example, the following query returns _Employee_ documents where `FirstName` is **not** `"Robert"`. + + + +```javascript +const employees = await session + .query({ collection: "Employees" }) + .not() // Negate the next predicate + .whereEquals("FirstName", "Robert") + .all(); +``` + + +```javascript +const employees = await session.advanced + .rawQuery("from Employees where FirstName != $firstName") + .addParameter("firstName", "Robert") + .all(); +``` + + +```sql +from Employees +where FirstName != "Robert" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Using whereNotEquals + +* The `not()` operator negates only the next predicate or subclause. + It cannot be used on its own; it must be followed by a predicate or by `openSubclause()`. + +* For a single equality condition, you can use `whereNotEquals` instead of `not().whereEquals`. + For example: + ```javascript + const employees = await session + .query({ collection: "Employees" }) + .whereNotEquals("FirstName", "Robert") + .all(); + ``` + is equivalent to: + ```javascript + const employees = await session + .query({ collection: "Employees" }) + .not() + .whereEquals("FirstName", "Robert") + .all(); + ``` + + + + + + + +Use **NOT** with grouping to negate multiple conditions as a single unit. + +For example, the following query returns _Employee_ documents that are **not** +(`FirstName` is `"Robert"` **and** `LastName` is `"King"`). + +In the query API, call `not()` before `openSubclause()` to negate the whole group. + + + +```javascript +const employees = await session + .query({ collection: "Employees" }) + .not() // Negate the whole group that follows + .openSubclause() // Open the group + .whereEquals("FirstName", "Robert") + .andAlso() + .whereEquals("LastName", "King") + .closeSubclause() // Close the group + .all(); +``` + + +```javascript +const employees = await session.advanced + .rawQuery("from Employees where true and not (FirstName = $firstName and LastName = $lastName)") + .addParameter("firstName", "Robert") + .addParameter("lastName", "King") + .all(); +``` + + +```sql +from Employees +where true and not (FirstName = "Robert" and LastName = "King") + +// In RQL, NOT cannot start a where clause; it must follow a valid preceding expression. +// Use true and not (...) when the whole where clause starts with a negated group. +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName` +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Alternative syntax + +* `not (A and B)` is equivalent to `not A or not B`. + For example, the query above: + `not (FirstName = "Robert" and LastName = "King")` + can also be expressed as: + `FirstName != "Robert" or LastName != "King"`. + +* In the query API, this is: + `.whereNotEquals("FirstName", "Robert").orElse().whereNotEquals("LastName", "King")`. + +* In **RQL**, this is: + `from Employees where FirstName != "Robert" or LastName != "King"`. + + + + + + + +When you mix **AND** and **OR** in the same query, use grouping to control which conditions are evaluated together. +In the query API, group conditions with `openSubclause()` and `closeSubclause()`; +in _RQL_, use parentheses. + +For example, the following query returns _Employee_ documents whose `Title` is `"Sales Representative"` +**and** whose `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```javascript +const employees = await session + .query({ collection: "Employees" }) + .whereEquals("Title", "Sales Representative") + .andAlso() + .openSubclause() // Group the OR conditions so they are evaluated together + .whereEquals("FirstName", "Robert") + .orElse() + .whereEquals("FirstName", "Nancy") + .closeSubclause() + .all(); +``` + + +```javascript +const employees = await session.advanced + .rawQuery( + "from Employees where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .addParameter("title", "Sales Representative") + .addParameter("firstName1", "Robert") + .addParameter("firstName2", "Nancy") + .all(); +``` + + +```sql +from Employees +where Title = "Sales Representative" and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndTitle` +> The auto-index is derived from the _Title_ and _FirstName_ fields referenced in the _where_ clause. + +--- + + + +#### Grouping matters + +Without the grouping, the query: +`Title = "Sales Representative" and FirstName = "Robert" or FirstName = "Nancy"` +is evaluated as: +`(Title = "Sales Representative" and FirstName = "Robert") or FirstName = "Nancy"`, +because **AND** has higher precedence than **OR** (see [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults)). +This returns a different set of documents than the grouped query. + + + + + + + +The logical operators work the same way when querying a static index. +The conditions in the `where` clause are evaluated against the index-fields. + +For example, if a static index defines `FirstName`, `LastName`, and `Title` fields, +you can combine conditions on those fields just as you would in a dynamic query: + + + +```javascript +class Employees_ByNameAndTitle extends AbstractJavaScriptIndexCreationTask { + constructor() { + super(); + + this.map("Employees", employee => { + return { + // The index fields + FirstName: employee.FirstName, + LastName: employee.LastName, + Title: employee.Title + }; + }); + } +} +``` + + +```javascript +const employees = await session + .query({ index: Employees_ByNameAndTitle }) + .whereEquals("Title", "Sales Representative") + .andAlso() + .openSubclause() + .whereEquals("FirstName", "Robert") + .orElse() + .whereEquals("FirstName", "Nancy") + .closeSubclause() + .all(); +``` + + +```javascript +const employees = await session.advanced + .rawQuery( + "from index 'Employees/ByNameAndTitle' " + + "where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)") + .addParameter("title", "Sales Representative") + .addParameter("firstName1", "Robert") + .addParameter("firstName2", "Nancy") + .all(); +``` + + +```sql +from index "Employees/ByNameAndTitle" +where Title = "Sales Representative" + and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + + + + + +* **Precedence:** + When AND and OR appear together without grouping, **AND is evaluated before OR**. + In other words, `a and b or c` is interpreted as `(a and b) or c`. + Use grouping (`openSubclause` / `closeSubclause` or parentheses) whenever you need a different evaluation order. + +* **Default operator:** + When consecutive `where*` predicates are written without an explicit + `andAlso` or `orElse` between them, they are combined with **AND** by default. + Use `andAlso` to make the implicit AND explicit, or `orElse` when you need OR. + +* **NOT requires a following predicate or subclause:** + The `not()` operator negates the predicate or subclause that comes immediately after it. + It cannot be used on its own. + + diff --git a/docs/querying/filtering-query-results/content/_use-logical-operators-php.mdx b/docs/querying/filtering-query-results/content/_use-logical-operators-php.mdx new file mode 100644 index 0000000000..9b6168ea25 --- /dev/null +++ b/docs/querying/filtering-query-results/content/_use-logical-operators-php.mdx @@ -0,0 +1,424 @@ +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'; + + + +* A query's `where` clause can combine multiple filtering conditions with logical operators. + This lets you express richer predicates than a single condition, for example: + _"products that are in stock **and** cost more than 50"_, or _"employees whose first name is Robert **or** Nancy"_. + +* This article covers the logical operators available when filtering query results: + **AND**, **OR**, and **NOT**, as well as how to **group conditions** to control operator precedence. + The examples are shown with: + * **Query** + the high-level query API (`$session->query`), using methods such as `whereEquals`, `whereNotEquals`, `andAlso`, `orElse`, and `not()`. + * **RawQuery** + the client API for executing an RQL string directly, with query parameters supplied by `addParameter`. + * **RQL** + the raw query language, using `and`, `or`, `not (...)`, and comparison operators such as `!=`. + RQL keywords are case-insensitive; the examples below use lowercase. + +* The same logical-operator rules apply when querying a collection dynamically + and when [querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index). + +* For filtering by field value, numeric value, nested field, collection, document ID, and other basic conditions, + see [Filter query results](../../../querying/filtering-query-results/filter-query-results.mdx). + +--- + +* In this article: + * [Combine conditions with AND](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-and) + * [Combine conditions with OR](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-or) + * [Negate a condition with NOT](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) + * [Negate a group of conditions](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-group-of-conditions) + * [Group conditions to control precedence](../../../querying/filtering-query-results/use-logical-operators.mdx#group-conditions-to-control-precedence) + * [Logical operators when querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index) + * [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults) + + + + + +Use the **AND** operator to return only documents that satisfy **all** conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is `"Robert"` **and** `LastName` is `"King"`. + + + +```php +$employees = $session + ->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->andAlso() // Combine the two predicates with 'andAlso' + ->whereEquals("LastName", "King") + ->toList(); +``` + + +```php +$employees = $session->advanced() + ->rawQuery(Employee::class, + "from Employees where FirstName = \$firstName and LastName = \$lastName") + ->addParameter("firstName", "Robert") + ->addParameter("lastName", "King") + ->toList(); +``` + + +```sql +from Employees +where FirstName = "Robert" and LastName = "King" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName`. +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Chaining conditions uses AND + +Consecutive `where*` predicates are combined with AND by default. +For example: +`->whereEquals("FirstName", "Robert")->whereEquals("LastName", "King")` +is equivalent to: +`->whereEquals("FirstName", "Robert")->andAlso()->whereEquals("LastName", "King")`. + + + + + + + +Use the **OR** operator to return documents that satisfy **at least one** of the specified conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```php +$employees = $session + ->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->orElse() // Combine the two predicates with 'orElse' + ->whereEquals("FirstName", "Nancy") + ->toList(); +``` + + +```php +$employees = $session->advanced() + ->rawQuery(Employee::class, + "from Employees where FirstName = \$firstName1 or FirstName = \$firstName2") + ->addParameter("firstName1", "Robert") + ->addParameter("firstName2", "Nancy") + ->toList(); +``` + + +```sql +from Employees +where FirstName = "Robert" or FirstName = "Nancy" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Use IN for multiple values on the same field + +When the same field is compared against multiple possible values, as in the example above, +you can use `whereIn` instead of repeating OR conditions. +See [Filter by multiple possible values](../../../querying/filtering-query-results/filter-query-results.mdx#filter-by-multiple-possible-values). + + + + + + + +Use the **NOT** operator to return only documents that do **not** satisfy the specified condition. + +For example, the following query returns _Employee_ documents where `FirstName` is **not** `"Robert"`. + + + +```php +$employees = $session + ->query(Employee::class) + ->not() // Negate the next predicate + ->whereEquals("FirstName", "Robert") + ->toList(); +``` + + +```php +$employees = $session->advanced() + ->rawQuery(Employee::class, "from Employees where FirstName != \$firstName") + ->addParameter("firstName", "Robert") + ->toList(); +``` + + +```sql +from Employees +where FirstName != "Robert" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Using whereNotEquals + +* The `not()` operator negates only the next predicate or subclause. + It cannot be used on its own; it must be followed by a predicate or by `openSubclause()`. + +* For a single equality condition, you can use `whereNotEquals` instead of `not()->whereEquals`. + For example: + ```php + $employees = $session + ->query(Employee::class) + ->whereNotEquals("FirstName", "Robert") + ->toList(); + ``` + is equivalent to: + ```php + $employees = $session + ->query(Employee::class) + ->not() + ->whereEquals("FirstName", "Robert") + ->toList(); + ``` + + + + + + + +Use **NOT** with grouping to negate multiple conditions as a single unit. + +For example, the following query returns _Employee_ documents that are **not** +(`FirstName` is `"Robert"` **and** `LastName` is `"King"`). + +In the query API, call `not()` before `openSubclause()` to negate the whole group. + + + +```php +$employees = $session + ->query(Employee::class) + ->not() // Negate the whole group that follows + ->openSubclause() // Open the group + ->whereEquals("FirstName", "Robert") + ->andAlso() + ->whereEquals("LastName", "King") + ->closeSubclause() // Close the group + ->toList(); +``` + + +```php +$employees = $session->advanced() + ->rawQuery(Employee::class, + "from Employees where true and not (FirstName = \$firstName and LastName = \$lastName)") + ->addParameter("firstName", "Robert") + ->addParameter("lastName", "King") + ->toList(); +``` + + +```sql +from Employees +where true and not (FirstName = "Robert" and LastName = "King") + +// In RQL, NOT cannot start a where clause; it must follow a valid preceding expression. +// Use true and not (...) when the whole where clause starts with a negated group. +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName` +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Alternative syntax + +* `not (A and B)` is equivalent to `not A or not B`. + For example, the query above: + `not (FirstName = "Robert" and LastName = "King")` + can also be expressed as: + `FirstName != "Robert" or LastName != "King"`. + +* In the query API, this is: + `->whereNotEquals("FirstName", "Robert")->orElse()->whereNotEquals("LastName", "King")`. + +* In **RQL**, this is: + `from Employees where FirstName != "Robert" or LastName != "King"`. + + + + + + + +When you mix **AND** and **OR** in the same query, use grouping to control which conditions are evaluated together. +In the query API, group conditions with `openSubclause()` and `closeSubclause()`; +in _RQL_, use parentheses. + +For example, the following query returns _Employee_ documents whose `Title` is `"Sales Representative"` +**and** whose `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```php +$employees = $session + ->query(Employee::class) + ->whereEquals("Title", "Sales Representative") + ->andAlso() + ->openSubclause() // Group the OR conditions so they are evaluated together + ->whereEquals("FirstName", "Robert") + ->orElse() + ->whereEquals("FirstName", "Nancy") + ->closeSubclause() + ->toList(); +``` + + +```php +$employees = $session->advanced() + ->rawQuery(Employee::class, + "from Employees where Title = \$title and (FirstName = \$firstName1 or FirstName = \$firstName2)") + ->addParameter("title", "Sales Representative") + ->addParameter("firstName1", "Robert") + ->addParameter("firstName2", "Nancy") + ->toList(); +``` + + +```sql +from Employees +where Title = "Sales Representative" and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndTitle` +> The auto-index is derived from the _Title_ and _FirstName_ fields referenced in the _where_ clause. + +--- + + + +#### Grouping matters + +Without the grouping, the query: +`Title = "Sales Representative" and FirstName = "Robert" or FirstName = "Nancy"` +is evaluated as: +`(Title = "Sales Representative" and FirstName = "Robert") or FirstName = "Nancy"`, +because **AND** has higher precedence than **OR** (see [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults)). +This returns a different set of documents than the grouped query. + + + + + + + +The logical operators work the same way when querying a static index. +The conditions in the `where` clause are evaluated against the index-fields. + +For example, if a static index defines `FirstName`, `LastName`, and `Title` fields, +you can combine conditions on those fields just as you would in a dynamic query: + + + +```php +class Employees_ByNameAndTitle extends AbstractIndexCreationTask +{ + public function __construct() + { + parent::__construct(); + + // The index fields are FirstName, LastName, and Title + $this->map = "from employee in docs.Employees " . + "select new { employee.FirstName, employee.LastName, employee.Title }"; + } +} +``` + + +```php +$employees = $session + ->query(Employee::class, Employees_ByNameAndTitle::class) + ->whereEquals("Title", "Sales Representative") + ->andAlso() + ->openSubclause() + ->whereEquals("FirstName", "Robert") + ->orElse() + ->whereEquals("FirstName", "Nancy") + ->closeSubclause() + ->toList(); +``` + + +```php +$employees = $session->advanced() + ->rawQuery(Employee::class, + "from index 'Employees/ByNameAndTitle' " . + "where Title = \$title and (FirstName = \$firstName1 or FirstName = \$firstName2)") + ->addParameter("title", "Sales Representative") + ->addParameter("firstName1", "Robert") + ->addParameter("firstName2", "Nancy") + ->toList(); +``` + + +```sql +from index "Employees/ByNameAndTitle" +where Title = "Sales Representative" + and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + + + + + +* **Precedence:** + When AND and OR appear together without grouping, **AND is evaluated before OR**. + In other words, `a and b or c` is interpreted as `(a and b) or c`. + Use grouping (`openSubclause` / `closeSubclause` or parentheses) whenever you need a different evaluation order. + +* **Default operator:** + When consecutive `where*` predicates are written without an explicit + `andAlso` or `orElse` between them, they are combined with **AND** by default. + Use `andAlso` to make the implicit AND explicit, or `orElse` when you need OR. + +* **NOT requires a following predicate or subclause:** + The `not()` operator negates the predicate or subclause that comes immediately after it. + It cannot be used on its own. + + diff --git a/docs/querying/filtering-query-results/content/_use-logical-operators-python.mdx b/docs/querying/filtering-query-results/content/_use-logical-operators-python.mdx new file mode 100644 index 0000000000..77eaa697d0 --- /dev/null +++ b/docs/querying/filtering-query-results/content/_use-logical-operators-python.mdx @@ -0,0 +1,428 @@ +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'; + + + +* A query's `where` clause can combine multiple filtering conditions with logical operators. + This lets you express richer predicates than a single condition, for example: + _"products that are in stock **and** cost more than 50"_, or _"employees whose first name is Robert **or** Nancy"_. + +* This article covers the logical operators available when filtering query results: + **AND**, **OR**, and **NOT**, as well as how to **group conditions** to control operator precedence. + The examples are shown with: + * **Query** + the high-level query API (`session.query`), using methods such as `where_equals`, `where_not_equals`, `and_also`, `or_else`, and `not_()`. + * **RawQuery** + the client API for executing an RQL string directly, with query parameters supplied by `add_parameter`. + * **RQL** + the raw query language, using `and`, `or`, `not (...)`, and comparison operators such as `!=`. + RQL keywords are case-insensitive; the examples below use lowercase. + +* The same logical-operator rules apply when querying a collection dynamically + and when [querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index). + +* For filtering by field value, numeric value, nested field, collection, document ID, and other basic conditions, + see [Filter query results](../../../querying/filtering-query-results/filter-query-results.mdx). + +--- + +* In this article: + * [Combine conditions with AND](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-and) + * [Combine conditions with OR](../../../querying/filtering-query-results/use-logical-operators.mdx#combine-conditions-with-or) + * [Negate a condition with NOT](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) + * [Negate a group of conditions](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-group-of-conditions) + * [Group conditions to control precedence](../../../querying/filtering-query-results/use-logical-operators.mdx#group-conditions-to-control-precedence) + * [Logical operators when querying a static index](../../../querying/filtering-query-results/use-logical-operators.mdx#logical-operators-when-querying-a-static-index) + * [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults) + + + + + +Use the **AND** operator to return only documents that satisfy **all** conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is `"Robert"` **and** `LastName` is `"King"`. + + + +```python +employees = list( + session.query(object_type=Employee) + .where_equals("FirstName", "Robert") + .and_also() # Combine the two predicates with 'and_also' + .where_equals("LastName", "King") +) +``` + + +```python +employees = list( + session.advanced + .raw_query("from Employees where FirstName = $firstName and LastName = $lastName", Employee) + .add_parameter("firstName", "Robert") + .add_parameter("lastName", "King") +) +``` + + +```sql +from Employees +where FirstName = "Robert" and LastName = "King" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName`. +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Chaining conditions uses AND + +Consecutive `where_*` predicates are combined with AND by default. +For example: +`.where_equals("FirstName", "Robert").where_equals("LastName", "King")` +is equivalent to: +`.where_equals("FirstName", "Robert").and_also().where_equals("LastName", "King")`. + + + + + + + +Use the **OR** operator to return documents that satisfy **at least one** of the specified conditions. + +For example, the following query returns _Employee_ documents where `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```python +employees = list( + session.query(object_type=Employee) + .where_equals("FirstName", "Robert") + .or_else() # Combine the two predicates with 'or_else' + .where_equals("FirstName", "Nancy") +) +``` + + +```python +employees = list( + session.advanced + .raw_query("from Employees where FirstName = $firstName1 or FirstName = $firstName2", Employee) + .add_parameter("firstName1", "Robert") + .add_parameter("firstName2", "Nancy") +) +``` + + +```sql +from Employees +where FirstName = "Robert" or FirstName = "Nancy" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Use IN for multiple values on the same field + +When the same field is compared against multiple possible values, as in the example above, +you can use `where_in` instead of repeating OR conditions. +See [Filter by multiple possible values](../../../querying/filtering-query-results/filter-query-results.mdx#filter-by-multiple-possible-values). + + + + + + + +Use the **NOT** operator to return only documents that do **not** satisfy the specified condition. + +For example, the following query returns _Employee_ documents where `FirstName` is **not** `"Robert"`. + + + +```python +employees = list( + session.query(object_type=Employee) + .not_() # Negate the next predicate + .where_equals("FirstName", "Robert") +) +``` + + +```python +employees = list( + session.advanced + .raw_query("from Employees where FirstName != $firstName", Employee) + .add_parameter("firstName", "Robert") +) +``` + + +```sql +from Employees +where FirstName != "Robert" +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstName` +> The auto-index is derived from the _FirstName_ field referenced in the _where_ clause. + +--- + + + +#### Using where_not_equals + +* The `not_()` operator negates only the next predicate or subclause. + It cannot be used on its own; it must be followed by a predicate or by `open_subclause()`. + +* For a single equality condition, you can use `where_not_equals` instead of `not_().where_equals`. + For example: + ```python + employees = list( + session.query(object_type=Employee) + .where_not_equals("FirstName", "Robert") + ) + ``` + is equivalent to: + ```python + employees = list( + session.query(object_type=Employee) + .not_() + .where_equals("FirstName", "Robert") + ) + ``` + + + + + + + +Use **NOT** with grouping to negate multiple conditions as a single unit. + +For example, the following query returns _Employee_ documents that are **not** +(`FirstName` is `"Robert"` **and** `LastName` is `"King"`). + +In the query API, call `not_()` before `open_subclause()` to negate the whole group. + + + +```python +employees = list( + session.query(object_type=Employee) + .not_() # Negate the whole group that follows + .open_subclause() # Open the group + .where_equals("FirstName", "Robert") + .and_also() + .where_equals("LastName", "King") + .close_subclause() # Close the group +) +``` + + +```python +employees = list( + session.advanced + .raw_query("from Employees where true and not (FirstName = $firstName and LastName = $lastName)", Employee) + .add_parameter("firstName", "Robert") + .add_parameter("lastName", "King") +) +``` + + +```sql +from Employees +where true and not (FirstName = "Robert" and LastName = "King") + +// In RQL, NOT cannot start a where clause; it must follow a valid preceding expression. +// Use true and not (...) when the whole where clause starts with a negated group. +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndLastName` +> The auto-index is derived from the _FirstName_ and _LastName_ fields referenced in the _where_ clause. + +--- + + + +#### Alternative syntax + +* `not (A and B)` is equivalent to `not A or not B`. + For example, the query above: + `not (FirstName = "Robert" and LastName = "King")` + can also be expressed as: + `FirstName != "Robert" or LastName != "King"`. + +* In the query API, this is: + `.where_not_equals("FirstName", "Robert").or_else().where_not_equals("LastName", "King")`. + +* In **RQL**, this is: + `from Employees where FirstName != "Robert" or LastName != "King"`. + + + + + + + +When you mix **AND** and **OR** in the same query, use grouping to control which conditions are evaluated together. +In the query API, group conditions with `open_subclause()` and `close_subclause()`; +in _RQL_, use parentheses. + +For example, the following query returns _Employee_ documents whose `Title` is `"Sales Representative"` +**and** whose `FirstName` is either `"Robert"` **or** `"Nancy"`. + + + +```python +employees = list( + session.query(object_type=Employee) + .where_equals("Title", "Sales Representative") + .and_also() + .open_subclause() # Group the OR conditions so they are evaluated together + .where_equals("FirstName", "Robert") + .or_else() + .where_equals("FirstName", "Nancy") + .close_subclause() +) +``` + + +```python +employees = list( + session.advanced + .raw_query( + "from Employees where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)", Employee) + .add_parameter("title", "Sales Representative") + .add_parameter("firstName1", "Robert") + .add_parameter("firstName2", "Nancy") +) +``` + + +```sql +from Employees +where Title = "Sales Representative" and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + +> **Auto-index used:** `Auto/Employees/ByFirstNameAndTitle` +> The auto-index is derived from the _Title_ and _FirstName_ fields referenced in the _where_ clause. + +--- + + + +#### Grouping matters + +Without the grouping, the query: +`Title = "Sales Representative" and FirstName = "Robert" or FirstName = "Nancy"` +is evaluated as: +`(Title = "Sales Representative" and FirstName = "Robert") or FirstName = "Nancy"`, +because **AND** has higher precedence than **OR** (see [Operator precedence and defaults](../../../querying/filtering-query-results/use-logical-operators.mdx#operator-precedence-and-defaults)). +This returns a different set of documents than the grouped query. + + + + + + + +The logical operators work the same way when querying a static index. +The conditions in the `where` clause are evaluated against the index-fields. + +For example, if a static index defines `FirstName`, `LastName`, and `Title` fields, +you can combine conditions on those fields just as you would in a dynamic query: + + + +```python +from ravendb.documents.indexes.abstract_index_creation_tasks import AbstractIndexCreationTask + + +class Employees_ByNameAndTitle(AbstractIndexCreationTask): + def __init__(self): + super().__init__() + # The index fields: FirstName, LastName, and Title + self.map = ( + "from employee in docs.Employees " + "select new { FirstName = employee.FirstName, " + "LastName = employee.LastName, Title = employee.Title }" + ) +``` + + +```python +employees = list( + session.query_index_type(Employees_ByNameAndTitle, Employee) + .where_equals("Title", "Sales Representative") + .and_also() + .open_subclause() + .where_equals("FirstName", "Robert") + .or_else() + .where_equals("FirstName", "Nancy") + .close_subclause() +) +``` + + +```python +employees = list( + session.advanced + .raw_query( + "from index 'Employees/ByNameAndTitle' " + "where Title = $title and (FirstName = $firstName1 or FirstName = $firstName2)", Employee) + .add_parameter("title", "Sales Representative") + .add_parameter("firstName1", "Robert") + .add_parameter("firstName2", "Nancy") +) +``` + + +```sql +from index "Employees/ByNameAndTitle" +where Title = "Sales Representative" + and (FirstName = "Robert" or FirstName = "Nancy") +``` + + + + + + + +* **Precedence:** + When AND and OR appear together without grouping, **AND is evaluated before OR**. + In other words, `a and b or c` is interpreted as `(a and b) or c`. + Use grouping (`open_subclause` / `close_subclause` or parentheses) whenever you need a different evaluation order. + +* **Default operator:** + When consecutive `where_*` predicates are written without an explicit + `and_also` or `or_else` between them, they are combined with **AND** by default. + Use `and_also` to make the implicit AND explicit, or `or_else` when you need OR. + +* **NOT requires a following predicate or subclause:** + The `not_()` operator negates the predicate or subclause that comes immediately after it. + It cannot be used on its own. + + From 241861d90a514ccaa4eff0e1659d92278f62c8b4 Mon Sep 17 00:00:00 2001 From: Danielle9897 Date: Thu, 11 Jun 2026 13:29:34 +0300 Subject: [PATCH 3/3] RDoc-3902 Remove the 'Not' article + update links --- .../querying/document-query/_category_.json | 4 -- .../_how-to-use-not-operator-csharp.mdx | 68 ------------------- .../content/_how-to-use-not-operator-java.mdx | 68 ------------------- .../_how-to-use-not-operator-nodejs.mdx | 65 ------------------ .../how-to-use-not-operator.mdx | 41 ----------- docs/querying/content/_overview-php.mdx | 2 +- docs/querying/content/_overview-python.mdx | 2 +- .../_what-is-document-query-csharp.mdx | 2 +- .../content/_what-is-document-query-java.mdx | 2 +- .../use-logical-operators.mdx | 22 +++++- docs/querying/rql/what-is-rql.mdx | 3 + scripts/redirects.json | 7 ++ 12 files changed, 35 insertions(+), 251 deletions(-) delete mode 100644 docs/client-api/session/querying/document-query/_category_.json delete mode 100644 docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-csharp.mdx delete mode 100644 docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-java.mdx delete mode 100644 docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-nodejs.mdx delete mode 100644 docs/client-api/session/querying/document-query/how-to-use-not-operator.mdx diff --git a/docs/client-api/session/querying/document-query/_category_.json b/docs/client-api/session/querying/document-query/_category_.json deleted file mode 100644 index 034d384f39..0000000000 --- a/docs/client-api/session/querying/document-query/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "position": 2, - "label": DocumentQuery, -} \ No newline at end of file diff --git a/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-csharp.mdx b/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-csharp.mdx deleted file mode 100644 index 642e82a87e..0000000000 --- a/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-csharp.mdx +++ /dev/null @@ -1,68 +0,0 @@ -import Admonition from '@theme/Admonition'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import CodeBlock from '@theme/CodeBlock'; - -`IDocumentQuery` contains `NOT` operator which can be used to negate **next** predicate - - -`NOT` operator cannot be used alone without succeeding predicate. - - -## Example I - - - -{`// load all entities from 'Employees' collection -// where FirstName NOT equals 'Robert' -List employees = session - .Advanced - .DocumentQuery() - .Not - .WhereEquals(x => x.FirstName, "Robert") - .ToList(); -`} - - - -## Example II - - - -{`// load all entities from 'Employees' collection -// where FirstName NOT equals 'Robert' -// and LastName NOT equals 'King' -List employees = session - .Advanced - .DocumentQuery() - .Not - .OpenSubclause() - .WhereEquals(x => x.FirstName, "Robert") - .AndAlso() - .WhereEquals(x => x.LastName, "King") - .CloseSubclause() - .ToList(); -`} - - - -## Example III - - - -{`// load all entities from 'Employees' collection -// where FirstName NOT equals 'Robert' -// and LastName NOT equals 'King' -// identical to 'Example II' but 'WhereNotEquals' is used -List employees = session - .Advanced - .DocumentQuery() - .WhereNotEquals(x => x.FirstName, "Robert") - .AndAlso() - .WhereNotEquals(x => x.LastName, "King") - .ToList(); -`} - - - - diff --git a/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-java.mdx b/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-java.mdx deleted file mode 100644 index cd36431a1b..0000000000 --- a/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-java.mdx +++ /dev/null @@ -1,68 +0,0 @@ -import Admonition from '@theme/Admonition'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import CodeBlock from '@theme/CodeBlock'; - -`IDocumentQuery` contains `NOT` operator which can be used to negate **next** predicate - - -`NOT` operator cannot be used alone without succeeding predicate. - - -## Example I - - - -{`// load all entities from 'Employees' collection -// where firstName NOT equals 'Robert' -List employees = session - .advanced() - .documentQuery(Employee.class) - .not() - .whereEquals("FirstName", "Robert") - .toList(); -`} - - - -## Example II - - - -{`// load all entities from 'Employees' collection -// where firstName NOT equals 'Robert' -// and lastName NOT equals 'King' -List employees = session - .advanced() - .documentQuery(Employee.class) - .not() - .openSubclause() - .whereEquals("FirstName", "Robert") - .andAlso() - .whereEquals("LastName", "King") - .closeSubclause() - .toList(); -`} - - - -## Example III - - - -{`// load all entities from 'Employees' collection -// where firstName NOT equals 'Robert' -// and lastName NOT equals 'King' -// identical to 'Example II' but 'whereNotEquals' is used -List employees = session - .advanced() - .documentQuery(Employee.class) - .whereNotEquals("FirstName", "Robert") - .andAlso() - .whereNotEquals("LastName", "King") - .toList(); -`} - - - - diff --git a/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-nodejs.mdx b/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-nodejs.mdx deleted file mode 100644 index f070e948c6..0000000000 --- a/docs/client-api/session/querying/document-query/content/_how-to-use-not-operator-nodejs.mdx +++ /dev/null @@ -1,65 +0,0 @@ -import Admonition from '@theme/Admonition'; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import CodeBlock from '@theme/CodeBlock'; - -`IDocumentQuery` contains `NOT` operator which can be used to negate **next** predicate - - -`NOT` operator cannot be used alone without succeeding predicate. - - -## Example I - - - -{`// load all entities from 'Employees' collection -// where firstName NOT equals 'Robert' -const employees = await session.advanced - .documentQuery(\{ collection: "Employees" \}) - .not() - .whereEquals("FirstName", "Robert") - .all(); -`} - - - -## Example II - - - -{`// load all entities from 'Employees' collection -// where firstName NOT equals 'Robert' -// and lastName NOT equals 'King' -const employees = await session.advanced - .documentQuery(\{ collection: "Employees" \}) - .not() - .openSubclause() - .whereEquals("FirstName", "Robert") - .andAlso() - .whereEquals("LastName", "King") - .closeSubclause() - .all(); -`} - - - -## Example III - - - -{`// load all entities from 'Employees' collection -// where firstName NOT equals 'Robert' -// and lastName NOT equals 'King' -// identical to 'Example II' but 'whereNotEquals' is used -const employees = await session.advanced - .documentQuery(\{ collection: "Employees" \}) - .whereNotEquals("FirstName", "Robert") - .andAlso() - .whereNotEquals("LastName", "King") - .all(); -`} - - - - diff --git a/docs/client-api/session/querying/document-query/how-to-use-not-operator.mdx b/docs/client-api/session/querying/document-query/how-to-use-not-operator.mdx deleted file mode 100644 index a87b5e7d22..0000000000 --- a/docs/client-api/session/querying/document-query/how-to-use-not-operator.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Session: Querying: How to Use NOT Operator" -sidebar_label: How to Use NOT Operator -description: "Negate query conditions in RavenDB using the Not operator with DocumentQuery to exclude documents matching specific criteria." -sidebar_position: 2 -supported_languages: ["csharp", "java", "nodejs"] -see_also: - - title: "What is Document Query" - link: "querying/document-query/what-is-document-query" - source: "docs" - path: "Querying > DocumentQuery" - - title: "Filter with Lucene Syntax" - link: "querying/filtering-query-results/filter-with-lucene-syntax" - source: "docs" - path: "Querying > Filtering query results" ---- - -import LanguageSwitcher from "@site/src/components/LanguageSwitcher"; -import LanguageContent from "@site/src/components/LanguageContent"; - -import HowToUseNotOperatorCsharp from './content/_how-to-use-not-operator-csharp.mdx'; -import HowToUseNotOperatorJava from './content/_how-to-use-not-operator-java.mdx'; -import HowToUseNotOperatorNodejs from './content/_how-to-use-not-operator-nodejs.mdx'; - - - - - - - - - - - - - - - - - - diff --git a/docs/querying/content/_overview-php.mdx b/docs/querying/content/_overview-php.mdx index edd40b0c26..16ecb53abe 100644 --- a/docs/querying/content/_overview-php.mdx +++ b/docs/querying/content/_overview-php.mdx @@ -401,7 +401,7 @@ Available methods for the session's [query](../../querying/overview.mdx#session- - [longCount](../../client-api/session/querying/how-to-count-query-results.mdx) - [moreLikeThis](../../client-api/session/querying/how-to-use-morelikethis.mdx) - negateNext -- [not](../../client-api/session/querying/document-query/how-to-use-not-operator.mdx) +- [not](../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) - [noCaching](../../querying/customize-query.mdx#nocaching) - [noTracking](../../querying/customize-query.mdx#notracking) - [ofType](../../client-api/session/querying/how-to-project-query-results.mdx#oftype-(as)---simple-projection) diff --git a/docs/querying/content/_overview-python.mdx b/docs/querying/content/_overview-python.mdx index 11022318e5..1a9a63df8d 100644 --- a/docs/querying/content/_overview-python.mdx +++ b/docs/querying/content/_overview-python.mdx @@ -456,7 +456,7 @@ Available methods for the session's [query](../../querying/overview.mdx#session- - [lazily](../../client-api/session/querying/how-to-perform-queries-lazily.mdx) - [more_like_this](../../client-api/session/querying/how-to-use-morelikethis.mdx) - negate_next -- [not](../../client-api/session/querying/document-query/how-to-use-not-operator.mdx) +- [not](../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) - [no_caching](../../querying/customize-query.mdx#nocaching) - [no_tracking](../../querying/customize-query.mdx#notracking) - [of_type](../../client-api/session/querying/how-to-project-query-results.mdx#oftype-(as)---simple-projection) diff --git a/docs/querying/document-query/content/_what-is-document-query-csharp.mdx b/docs/querying/document-query/content/_what-is-document-query-csharp.mdx index a3f281235e..02364ae028 100644 --- a/docs/querying/document-query/content/_what-is-document-query-csharp.mdx +++ b/docs/querying/document-query/content/_what-is-document-query-csharp.mdx @@ -327,7 +327,7 @@ Available custom methods and extensions: - [LongCount](../../../client-api/session/querying/how-to-count-query-results.mdx) - MoreLikeThis - NegateNext -- [Not](../../../client-api/session/querying/document-query/how-to-use-not-operator.mdx) +- [Not](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) - [Query] [NoCaching](../../../querying/customize-query.mdx#nocaching) - [Query] [NoTracking](../../../querying/customize-query.mdx#notracking) - OfType diff --git a/docs/querying/document-query/content/_what-is-document-query-java.mdx b/docs/querying/document-query/content/_what-is-document-query-java.mdx index cccad4bd52..20a565c230 100644 --- a/docs/querying/document-query/content/_what-is-document-query-java.mdx +++ b/docs/querying/document-query/content/_what-is-document-query-java.mdx @@ -121,7 +121,7 @@ Available methods: - moreLikeThis - negateNext - [Query] [noCaching](../../../querying/customize-query.mdx#nocaching) -- [not](../../../client-api/session/querying/document-query/how-to-use-not-operator.mdx) +- [not](../../../querying/filtering-query-results/use-logical-operators.mdx#negate-a-condition-with-not) - [Query] [noTracking](../../../querying/customize-query.mdx#notracking) - ofType - openSubclause diff --git a/docs/querying/filtering-query-results/use-logical-operators.mdx b/docs/querying/filtering-query-results/use-logical-operators.mdx index cbee392022..6287300a00 100644 --- a/docs/querying/filtering-query-results/use-logical-operators.mdx +++ b/docs/querying/filtering-query-results/use-logical-operators.mdx @@ -3,7 +3,7 @@ title: "Use Logical Operators" sidebar_label: "Use Logical Operators" description: "Learn how to combine multiple filtering conditions in a query using the logical operators AND, OR, and NOT, and how to group conditions to control their evaluation order." sidebar_position: 2 -supported_languages: ["csharp"] +supported_languages: ["csharp", "nodejs", "python", "php", "java"] see_also: - title: "Filter Query Results" link: "querying/filtering-query-results/filter-query-results" @@ -23,9 +23,29 @@ import LanguageSwitcher from "@site/src/components/LanguageSwitcher"; import LanguageContent from "@site/src/components/LanguageContent"; import UseLogicalOperatorsCsharp from './content/_use-logical-operators-csharp.mdx'; +import UseLogicalOperatorsNodejs from './content/_use-logical-operators-nodejs.mdx'; +import UseLogicalOperatorsPython from './content/_use-logical-operators-python.mdx'; +import UseLogicalOperatorsPhp from './content/_use-logical-operators-php.mdx'; +import UseLogicalOperatorsJava from './content/_use-logical-operators-java.mdx'; + + + + + + + + + + + + + + + + diff --git a/docs/querying/rql/what-is-rql.mdx b/docs/querying/rql/what-is-rql.mdx index d3a63678fc..c3695f5d5d 100644 --- a/docs/querying/rql/what-is-rql.mdx +++ b/docs/querying/rql/what-is-rql.mdx @@ -418,6 +418,8 @@ where Lines[].ProductName all in ("Chang", "Spegesild") Binary operators can be used to build more complex statements. The `NOT` operator can only be used with one of the other binary operators creating `OR NOT` or `AND NOT` ones. +Learn more about combining filter conditions with these operators in [Use logical operators](../../querying/filtering-query-results/use-logical-operators.mdx). + ```sql from "Companies" @@ -471,6 +473,7 @@ where RequiredAt >= now() #### Subclauses:    `(`, `)` Subclauses can be used along with binary operators to build even more complex logical statements. +See [Group conditions to control precedence](../../querying/filtering-query-results/use-logical-operators.mdx#group-conditions-to-control-precedence). diff --git a/scripts/redirects.json b/scripts/redirects.json index ec5d739632..495b239788 100644 --- a/scripts/redirects.json +++ b/scripts/redirects.json @@ -962,5 +962,12 @@ "targetUrl": "/querying/filtering-query-results/filter-with-lucene-syntax", "minimumVersion": "7.2" } + }, + { + "key": "/client-api/session/querying/document-query/how-to-use-not-operator", + "value": { + "targetUrl": "/querying/filtering-query-results/use-logical-operators", + "minimumVersion": "7.2" + } } ]