diff --git a/docs/client-api/session/querying/content/_how-to-filter-by-field-csharp.mdx b/docs/client-api/session/querying/content/_how-to-filter-by-field-csharp.mdx index f6dd752a57..d7b2fe1450 100644 --- a/docs/client-api/session/querying/content/_how-to-filter-by-field-csharp.mdx +++ b/docs/client-api/session/querying/content/_how-to-filter-by-field-csharp.mdx @@ -2,26 +2,33 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; * To query for documents that contain a particular field, - use extension method `WhereExists()` which is accessible from [DocumentQuery](../../../../querying/document-query/what-is-document-query.mdx). + use the `WhereExists()` extension method which is accessible from [DocumentQuery](../../../../querying/document-query/what-is-document-query.mdx). * A document that doesn't contain the specified field will be excluded from the query results. + +* `WhereExists()` filters documents by field presence, not by how relevant the field's value is. + When you [order results by score](../../../../querying/sorting-query-results/sort-query-results.mdx#order-by-score), `WhereExists()` can contribute to that score. + For how this contribution works with Corax, see [Corax: Scoring](../../../../indexes/search-engine/corax.mdx#scoring). -* In this page: - * [Filter by field name](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-name) - * [Filter by field path](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-path) - * [Syntax](../../../../client-api/session/querying/how-to-filter-by-field.mdx#syntax) +* In this article: + * [Filter by field name](#filter-by-field-name) + * [Filter by field path](#filter-by-field-path) + * [Syntax](#syntax) -## Filter by field name + + - -{`// Only documents that contain field 'FirstName' will be returned +```csharp +// Only documents that contain field 'FirstName' will be returned List results = session .Advanced @@ -29,12 +36,11 @@ List results = session .WhereExists("FirstName") // Or use lambda expression: .WhereExists(x => x.FirstName) .ToList(); -`} - +``` - -{`// Only documents that contain field 'FirstName' will be returned +```csharp +// Only documents that contain field 'FirstName' will be returned List results = await asyncSession .Advanced @@ -42,28 +48,26 @@ List results = await asyncSession .WhereExists("FirstName") // Or use lambda expression: .WhereExists(x => x.FirstName) .ToListAsync(); -`} - +``` - -{`// Only documents that contain field 'FirstName' will be returned +```sql +// Only documents that contain field 'FirstName' will be returned from Employees where exists("FirstName") -`} - +``` + + - - -## Filter by field path + - -{`// Only documents that contain the 'Latitude' property in the specified path will be returned +```csharp +// Only documents that contain the 'Latitude' property in the specified path will be returned List results = session .Advanced @@ -71,12 +75,11 @@ List results = session .WhereExists("Address.Location.Latitude") // Or use lambda expression: .WhereExists(x => x.Address.Location.Latitude) .ToList(); -`} - +``` - -{`// Only documents that contain the 'Latitude' property in the specified path will be returned +```csharp +// Only documents that contain the 'Latitude' property in the specified path will be returned List results = await asyncSession .Advanced @@ -84,38 +87,31 @@ List results = await asyncSession .WhereExists("Address.Location.Latitude") // Or use lambda expression: .WhereExists(x => x.Address.Location.Latitude) .ToListAsync(); -`} - +``` - -{`// Only documents that contain the 'Latitude' property in the specified path will be returned +```sql +// Only documents that contain the 'Latitude' property in the specified path will be returned from Employees where exists("Address.Location.Latitude") -`} - +``` + + -## Syntax - - - -{`IDocumentQuery WhereExists(string fieldName); - +```csharp +IDocumentQuery WhereExists(string fieldName); IDocumentQuery WhereExists(Expression> propertySelector); -`} - - +``` +
-| Parameters | Type | Description | +| Parameter | Type | Description | |----------------------|------------------------------|-----------------------------------------------------------------------| | **fieldName** | `string` | The name / path of the document field to filter by | | **propertySelector** | `Expression>` | Lambda expression with name / path of the document field to filter by | - - - +
\ No newline at end of file diff --git a/docs/client-api/session/querying/content/_how-to-filter-by-field-java.mdx b/docs/client-api/session/querying/content/_how-to-filter-by-field-java.mdx index 7d396fc851..c26e125764 100644 --- a/docs/client-api/session/querying/content/_how-to-filter-by-field-java.mdx +++ b/docs/client-api/session/querying/content/_how-to-filter-by-field-java.mdx @@ -2,81 +2,86 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* To filter documents by whether they contain a particular field, use the LINQ extension method `whereExists()` accessible -from the [Document Query](../../../../querying/document-query/what-is-document-query.mdx). +* Use method `whereExists()` to query for documents that contain a particular field. + A document that doesn't contain the specified field will be excluded from the query results. -* If a document doesn't contain the specified field, it is excluded from the query results. +* `whereExists()` filters documents by field presence, not by how relevant the field's value is. + When you [order results by score](../../../../querying/sorting-query-results/sort-query-results.mdx#order-by-score), `whereExists()` can contribute to that score. + For how this contribution works with Corax, see [Corax: Scoring](../../../../indexes/search-engine/corax.mdx#scoring). -* In this page: - * [Syntax](../../../../client-api/session/querying/how-to-filter-by-field.mdx#syntax) - * [Examples](../../../../client-api/session/querying/how-to-filter-by-field.mdx#examples) +* In this article: + * [Filter by field name](#filter-by-field-name) + * [Filter by field path](#filter-by-field-path) + * [Syntax](#syntax) -## Syntax - - -{`IDocumentQuery whereExists(String fieldName); -`} - - - -| Parameters | Type | Description | -| - | - | - | -| **fieldName** | `String` | The name or path to the field you want to filter by | - - - -## Examples - -#### Filter by Field Name + - - -{`List results = session - .advanced() - .documentQuery(Employee.class) - .whereExists("FirstName") - .toList(); -`} - + +```java +// Only documents that contain field 'FirstName' will be returned + +List results = session + .advanced() + .documentQuery(Employee.class) + .whereExists("FirstName") + .toList(); +``` - -{`from Employees +```sql +// Only documents that contain field 'FirstName' will be returned + +from Employees where exists("FirstName") -`} - +``` + -#### Filter by the Path to a Field + - - -{`List results = session - .advanced() - .documentQuery(Employee.class) - .whereExists("Address.Location.Latitude") - .toList(); -`} - + +```java +// Only documents that contain the 'Latitude' property in the specified path will be returned + +List results = session + .advanced() + .documentQuery(Employee.class) + .whereExists("Address.Location.Latitude") + .toList(); +``` - -{`from Employees +```sql +// Only documents that contain the 'Latitude' property in the specified path will be returned + +from Employees where exists("Address.Location.Latitude") -`} - +``` + + + +```java +IDocumentQuery whereExists(String fieldName); +``` +
+| Parameter | Type | Description | +|---------------|----------|----------------------------------------------------| +| **fieldName** | `String` | The name / path of the document field to filter by | +
diff --git a/docs/client-api/session/querying/content/_how-to-filter-by-field-nodejs.mdx b/docs/client-api/session/querying/content/_how-to-filter-by-field-nodejs.mdx index 984ca5bf62..d10151c6e5 100644 --- a/docs/client-api/session/querying/content/_how-to-filter-by-field-nodejs.mdx +++ b/docs/client-api/session/querying/content/_how-to-filter-by-field-nodejs.mdx @@ -2,84 +2,82 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; * Use method `whereExists()` to query for documents that contain a particular field. + A document that doesn't contain the specified field will be excluded from the query results. -* A document that doesn't contain the specified field will be excluded from the query results. +* `whereExists()` filters documents by field presence, not by how relevant the field's value is. + When you [order results by score](../../../../querying/sorting-query-results/sort-query-results.mdx#order-by-score), `whereExists()` can contribute to that score. + For how this contribution works with Corax, see [Corax: Scoring](../../../../indexes/search-engine/corax.mdx#scoring). -* In this page: - * [Filter by field name](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-name) - * [Filter by field path](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-path) - * [Syntax](../../../../client-api/session/querying/how-to-filter-by-field.mdx#syntax) +* In this article: + * [Filter by field name](#filter-by-field-name) + * [Filter by field path](#filter-by-field-path) + * [Syntax](#syntax) -## Filter by field name + + - -{`// Only documents that contain field 'firstName' will be returned +```js +// Only documents that contain field 'firstName' will be returned await session.query({ collection: "Employees" }) - .whereExists("firstName"); + .whereExists("firstName") .all(); -`} - +``` - -{`// Only documents that contain field 'firstName' will be returned +```sql +// Only documents that contain field 'firstName' will be returned from Employees where exists("firstName") -`} - +``` + - -## Filter by field path + - -{`// Only documents that contain the 'latitude' property in the specified path will be returned +```js +// Only documents that contain the 'latitude' property in the specified path will be returned await session.query({ collection: "Employees" }) - .whereExists("address.location.latitude"); + .whereExists("address.location.latitude") .all(); -`} - +``` - -{`// Only documents that contain the 'latitude' property in the specified path will be returned +```sql +// Only documents that contain the 'latitude' property in the specified path will be returned from Employees where exists("address.location.latitude") -`} - +``` + + -## Syntax - - - -{`whereExists(fieldName); -`} - - - -| Parameters | Type | Description | -|----------------------|------------------------------|----------------------------------------------------| -| **fieldName** | `string` | The name / path of the document field to filter by | - - +```js +whereExists(fieldName); +``` +
+| Parameter | Type | Description | +|---------------|----------|----------------------------------------------------| +| **fieldName** | `string` | The name / path of the document field to filter by | +
diff --git a/docs/client-api/session/querying/content/_how-to-filter-by-field-php.mdx b/docs/client-api/session/querying/content/_how-to-filter-by-field-php.mdx index 84bd60c3ad..6461e97e0f 100644 --- a/docs/client-api/session/querying/content/_how-to-filter-by-field-php.mdx +++ b/docs/client-api/session/querying/content/_how-to-filter-by-field-php.mdx @@ -2,85 +2,87 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* To query for documents that contain a particular field, use the `whereExists` extension method. +* Use method `whereExists()` to query for documents that contain a particular field. + A document that doesn't contain the specified field will be excluded from the query results. -* A document that doesn't contain the specified field will be excluded from the query results. +* `whereExists()` filters documents by field presence, not by how relevant the field's value is. + When you [order results by score](../../../../querying/sorting-query-results/sort-query-results.mdx#order-by-score), `whereExists()` can contribute to that score. + For how this contribution works with Corax, see [Corax: Scoring](../../../../indexes/search-engine/corax.mdx#scoring). -* In this page: - * [Filter by field name](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-name) - * [Filter by field path](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-path) - * [Syntax](../../../../client-api/session/querying/how-to-filter-by-field.mdx#syntax) +* In this article: + * [Filter by field name](#filter-by-field-name) + * [Filter by field path](#filter-by-field-path) + * [Syntax](#syntax) -## Filter by field name + + - - -{`/** @var array $results */ + +```php +// Only documents that contain field 'FirstName' will be returned + +/** @var array $results */ $results = $session ->advanced() ->documentQuery(Employee::class) ->whereExists("FirstName") ->toList(); -`} - +``` - -{`// Only documents that contain field 'FirstName' will be returned +```sql +// Only documents that contain field 'FirstName' will be returned from Employees where exists("FirstName") -`} - +``` + - -## Filter by field path + - - -{`$results = $session + +```php +// Only documents that contain the 'Latitude' property in the specified path will be returned + +$results = $session ->advanced() ->documentQuery(Employee::class) ->whereExists("Address.Location.Latitude") ->toList(); -`} - +``` - -{`// Only documents that contain the 'Latitude' property in the specified path will be returned +```sql +// Only documents that contain the 'Latitude' property in the specified path will be returned from Employees where exists("Address.Location.Latitude") -`} - +``` + + -## Syntax - - - -{`public function whereExists(?string $fieldName): DocumentQueryInterface; -`} - - - -| Parameters | Type | Description | -|----------------|-----------|----------------------------------------------------| -| **$fieldName** | `?string` | The name / path of the document field to filter by | - - +```php +public function whereExists(string $fieldName): DocumentQueryInterface; +``` +
+| Parameter | Type | Description | +|----------------|----------|----------------------------------------------------| +| **$fieldName** | `string` | The name / path of the document field to filter by | +
diff --git a/docs/client-api/session/querying/content/_how-to-filter-by-field-python.mdx b/docs/client-api/session/querying/content/_how-to-filter-by-field-python.mdx index 89729711e3..44f679c725 100644 --- a/docs/client-api/session/querying/content/_how-to-filter-by-field-python.mdx +++ b/docs/client-api/session/querying/content/_how-to-filter-by-field-python.mdx @@ -2,81 +2,80 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* To search for documents that contain a specific field by the field **name** or **path**, - use the [document_query](../../../../querying/document-query/what-is-document-query.mdx) - `where_exists` method. - Documents that do not contain the specified field will be excluded from the query results. +* Use method `where_exists()` to query for documents that contain a particular field. + A document that doesn't contain the specified field will be excluded from the query results. -* In this page: - * [Filter by Field Name or Path](../../../../client-api/session/querying/how-to-filter-by-field.mdx#filter-by-field-name-or-path) - * [Syntax](../../../../client-api/session/querying/how-to-filter-by-field.mdx#syntax) - * [Examples](../../../../client-api/session/querying/how-to-filter-by-field.mdx#examples) +* `where_exists()` filters documents by field presence, not by how relevant the field's value is. + When you [order results by score](../../../../querying/sorting-query-results/sort-query-results.mdx#order-by-score), `where_exists()` can contribute to that score. + For how this contribution works with Corax, see [Corax: Scoring](../../../../indexes/search-engine/corax.mdx#scoring). - -## Filter by Field Name or Path - -To search for documents that contain a specific field by the field's **name** or **path**, -pass the name or the path to `where_exists` as demonstrated below. -### Syntax +* In this article: + * [Filter by field name](#filter-by-field-name) + * [Filter by field path](#filter-by-field-path) + * [Syntax](#syntax) - - -{`def where_exists(self, field_name: str) -> DocumentQuery[_T]: ... -`} - - - -| Parameters | Type | Description | -|----------------------|-------------|-------------------------------------------| -| **field_name** | `str` | Field Name or Path to filter documents by | -### Examples + -Pass `where_exists` a string containing the field name or path. + -* **Pass a Field Name**: - -{`# Only documents that contain field 'first_name' will be returned -results = list(session.advanced.document_query(object_type=Employee).where_exists("first_name")) -`} - +```python +# Only documents that contain field 'FirstName' will be returned + +results = list(session.advanced.document_query(object_type=Employee).where_exists("FirstName")) +``` - -{`// Only documents that contain the 'FirstName' field will be returned +```sql +// Only documents that contain the 'FirstName' field will be returned from Employees where exists("FirstName") -`} - +``` -* **Pass a Field Path**: + + + + - -{`results = list( - session.advanced.document_query(object_type=Employee).where_exists("address.location.latitude") +```python +# Only documents that contain the 'Latitude' property in the specified path will be returned + +results = list( + session.advanced.document_query(object_type=Employee).where_exists("Address.Location.Latitude") ) -`} - +``` - -{`// Only documents that contain the 'Latitude' property in the specified path will be returned +```sql +// Only documents that contain the 'Latitude' property in the specified path will be returned from Employees where exists("Address.Location.Latitude") -`} - +``` + + + +```python +def where_exists(self, field_name: str) -> DocumentQuery[_T]: ... +``` +
+| Parameter | Type | Description | +|----------------|-------|----------------------------------------------------| +| **field_name** | `str` | The name / path of the document field to filter by | +
diff --git a/docs/client-api/session/querying/text-search/boost-search-results.mdx b/docs/client-api/session/querying/text-search/boost-search-results.mdx index 0c4407c435..0136b24dd5 100644 --- a/docs/client-api/session/querying/text-search/boost-search-results.mdx +++ b/docs/client-api/session/querying/text-search/boost-search-results.mdx @@ -3,7 +3,7 @@ title: "Boost Search Results" sidebar_label: Boost Search Results description: "Boost specific query terms in RavenDB full-text search to increase their influence on document relevance scoring and result ranking." sidebar_position: 4 -supported_languages: ["csharp", "python", "php", "nodejs"] +supported_languages: ["csharp", "java", "python", "php", "nodejs"] see_also: - title: "Query overview" link: "querying/overview" @@ -23,6 +23,7 @@ import LanguageSwitcher from "@site/src/components/LanguageSwitcher"; import LanguageContent from "@site/src/components/LanguageContent"; import BoostSearchResultsCsharp from './content/_boost-search-results-csharp.mdx'; +import BoostSearchResultsJava from './content/_boost-search-results-java.mdx'; import BoostSearchResultsPython from './content/_boost-search-results-python.mdx'; import BoostSearchResultsPhp from './content/_boost-search-results-php.mdx'; import BoostSearchResultsNodejs from './content/_boost-search-results-nodejs.mdx'; @@ -34,6 +35,10 @@ import BoostSearchResultsNodejs from './content/_boost-search-results-nodejs.mdx + + + + diff --git a/docs/client-api/session/querying/text-search/content/_boost-search-results-csharp.mdx b/docs/client-api/session/querying/text-search/content/_boost-search-results-csharp.mdx index 8adc0fc4d9..d8e92f73c8 100644 --- a/docs/client-api/session/querying/text-search/content/_boost-search-results-csharp.mdx +++ b/docs/client-api/session/querying/text-search/content/_boost-search-results-csharp.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -25,21 +27,22 @@ import CodeBlock from '@theme/CodeBlock'; * The calculated score details of the results can be retrieved if needed. Learn more here: [get resulting score](../../../../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) -* In this page: - - * [Boost results - when making a full-text search](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-making-a-full-text-search) - * [Boost results - when querying with where clause](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-querying-with-where-clause) +* In this article: + * [Boost results - when making a full-text search](#boost-results-when-making-a-full-text-search) + * [Boost results - when querying with where clause](#boost-results-when-querying-with-where-clause) + * [Boost a WhereExists() condition with Corax](#boost-a-whereexists-condition-with-corax) -## Boost results - when making a full-text search + + When making a full-text search with the `Search()` method then boosting can be applied to both `Query` and `DocumentQuery`. - -{`List employees = session +```csharp +List employees = session // Make a dynamic full-text search Query on 'Employees' collection .Query() // This search predicate will use the default boost value of 1 @@ -56,12 +59,11 @@ to both `Query` and `DocumentQuery`. // than those that contain 'English'. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`List employees = await asyncSession +```csharp +List employees = await asyncSession // Make a dynamic full-text search Query on 'Employees' collection .Query() // This search predicate will use the default boost value of 1 @@ -78,12 +80,11 @@ to both `Query` and `DocumentQuery`. // than those that contain 'English'. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`List employees = session.Advanced +```csharp +List employees = session.Advanced // Make a dynamic full-text search DocumentQuery on 'Employees' collection .DocumentQuery() // This search predicate will use the default boost value of 1 @@ -101,29 +102,27 @@ to both `Query` and `DocumentQuery`. // than those that contain 'English'. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`from "Employees" where +```sql +from "Employees" where search(Notes, "English") or boost(search(Notes, "Italian"), 10) -`} - +``` + - -## Boost results - when querying with where clause + When querying with `Where` clauses (using an OR condition in between) then boosting can be applied -only with `DocuemtQuery`. +only with `DocumentQuery`. - -{`List companies = session.Advanced +```csharp +List companies = session.Advanced // Make a dynamic DocumentQuery on 'Companies' collection .DocumentQuery() // Define a 'Where' condition @@ -146,12 +145,11 @@ only with `DocuemtQuery`. // Matching documents that start-with 'O' will get the LOWEST scores. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`List companies = await asyncSession.Advanced +```csharp +List companies = await asyncSession.Advanced // Make a dynamic DocumentQuery on 'Companies' collection .AsyncDocumentQuery() // Define a 'Where' condition @@ -174,20 +172,31 @@ only with `DocuemtQuery`. // Matching documents that start-with 'O' will get the LOWEST scores. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`from "Companies" where +```sql +from "Companies" where boost(startsWith(Name, "O"), 10) or boost(startsWith(Name, "P"), 50) or boost(endsWith(Name, "OP"), 90) -`} - +``` - - - + + +### Boost a `WhereExists()` condition with Corax + +In RavenDB 7.2.6 and later, when using the Corax search engine, a boosted `WhereExists()` condition (`exists()` in RQL) +contributes `1` multiplied by the query boost, rather than a relevance score calculated from the field's values. + +For example, `.WhereExists(x => x.Fax).Boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` +once per matching document, before any index-entry boost is applied. + +The `WhereStartsWith()` and `WhereEndsWith()` conditions in the example above use relevance-based scoring. +Learn more in [Corax: Scoring](../../../../../indexes/search-engine/corax.mdx#scoring). + + + + \ No newline at end of file diff --git a/docs/client-api/session/querying/text-search/content/_boost-search-results-java.mdx b/docs/client-api/session/querying/text-search/content/_boost-search-results-java.mdx new file mode 100644 index 0000000000..976095dbe4 --- /dev/null +++ b/docs/client-api/session/querying/text-search/content/_boost-search-results-java.mdx @@ -0,0 +1,133 @@ +import Admonition from '@theme/Admonition'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; + + + +* When querying with some filtering conditions, + a basic score is calculated for each document in the results by the underlying engine. + +* Providing a boost value to some fields allows you to prioritize the resulting documents. + The boost value is integrated with the basic score, making the document rank higher. + +* Boosting can be achieved in the following ways: + + * **At query time**: + Apply a boost factor to searched terms at query time - as described in this article. + + * **Via index definition**: + Apply a boost factor in your index definition - see this [boosting](../../../../../indexes/boosting.mdx) indexing article. + +* The automatic ordering of the results by the score is configurable. + Learn more here: [automatic score-based ordering](../../../../../indexes/boosting.mdx#automatic-score-based-ordering) + +* The calculated score details of the results can be retrieved if needed. + Learn more here: [get resulting score](../../../../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) + +* In this article: + * [Boost results - when making a full-text search](#boost-results-when-making-a-full-text-search) + * [Boost results - when querying with where clause](#boost-results-when-querying-with-where-clause) + * [Boost a whereExists() condition with Corax](#boost-a-whereexists-condition-with-corax) + + + + + +To apply boosting while running a full-text search, use the +`boost()` method to prioritize the preceding `search()` results. + + + +```java +List employees = session + // Make a dynamic full-text search query on 'Employees' collection + .query(Employee.class) + // This search predicate will use the default boost value of 1 + .search("Notes", "English") + // This search predicate will use a boost value of 10 + .search("Notes", "Italian") + // Call 'boost' to set the boost value of the previous 'search' call + .boost(10) + .toList(); + +// * Results will contain all Employee documents that have +// EITHER 'English' OR 'Italian' in their 'Notes' field (case-insensitive). +// +// * Matching documents that contain 'Italian' will get a HIGHER score +// than those that contain 'English'. +// +// * Unless configured otherwise, the resulting documents will be ordered by their score. +``` + + +```sql +from "Employees" where +search(Notes, "English") or boost(search(Notes, "Italian"), 10) +``` + + + + + + + +`boost()` can be used to give different priorities to the results +returned by different `where` clauses. + + + +```java +List companies = session + // Make a dynamic query on 'Companies' collection + .query(Company.class) + // Define a 'where' condition + .whereStartsWith("Name", "O") + // Call 'boost' to set the boost value of the previous 'where' predicate + .boost(10) + // Call 'orElse' so that OR operator will be used between statements + .orElse() + .whereStartsWith("Name", "P") + .boost(50) + .orElse() + .whereEndsWith("Name", "OP") + .boost(90) + .toList(); + +// * Results will contain all Company documents that either +// (start-with 'O') OR (start-with 'P') OR (end-with 'OP') in their 'Name' field (case-insensitive). +// +// * Matching documents that end-with 'OP' will get the HIGHEST scores. +// Matching documents that start-with 'O' will get the LOWEST scores. +// +// * Unless configured otherwise, the resulting documents will be ordered by their score. +``` + + +```sql +from "Companies" where +boost(startsWith(Name, "O"), 10) or +boost(startsWith(Name, "P"), 50) or +boost(endsWith(Name, "OP"), 90) +``` + + + + + +### Boost a `whereExists()` condition with Corax + +In RavenDB 7.2.6 and later, when using the Corax search engine, a boosted `whereExists()` condition (`exists()` in RQL) +contributes `1` multiplied by the query boost, rather than a relevance score calculated from the field's values. + +For example, `.whereExists("Fax").boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` +once per matching document, before any index-entry boost is applied. + +The `whereStartsWith()` and `whereEndsWith()` conditions in the example above use relevance-based scoring. +Learn more in [Corax: Scoring](../../../../../indexes/search-engine/corax.mdx#scoring). + + + + diff --git a/docs/client-api/session/querying/text-search/content/_boost-search-results-nodejs.mdx b/docs/client-api/session/querying/text-search/content/_boost-search-results-nodejs.mdx index f78176c12e..6dde0da773 100644 --- a/docs/client-api/session/querying/text-search/content/_boost-search-results-nodejs.mdx +++ b/docs/client-api/session/querying/text-search/content/_boost-search-results-nodejs.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -9,9 +11,9 @@ import CodeBlock from '@theme/CodeBlock'; a basic score is calculated for each document in the results by the underlying engine. * Providing a boost value to some fields allows you to prioritize the resulting documents. - The boost value is integrated with the basic score, making the document rank higher. + The boost value is integrated with the basic score, making the document rank higher. -* Boosting can be achieved in the following ways: +* Boosting can be achieved in the following ways: * **At query time**: Apply a boost factor to searched terms at query time - as described in this article. @@ -25,20 +27,22 @@ import CodeBlock from '@theme/CodeBlock'; * The calculated score details of the results can be retrieved if needed. Learn more here: [get resulting score](../../../../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) -* In this page: - - * [Boost results - when making a full-text search](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-making-a-full-text-search) - * [Boost results - when querying with where clause](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-querying-with-where-clause) +* In this article: + * [Boost results - when making a full-text search](#boost-results-when-making-a-full-text-search) + * [Boost results - when querying with where clause](#boost-results-when-querying-with-where-clause) + * [Boost a whereExists() condition with Corax](#boost-a-whereexists-condition-with-corax) -## Boost results - when making a full-text search - + + +To apply boosting while running a full-text search, use the +`boost()` method to prioritize the preceding `search()` results. - -{`const employees = await session +```js +const employees = await session // Make a dynamic full-text search Query on 'Employees' collection .query({ collection: "Employees"}) // This search predicate will use the default boost value of 1 @@ -56,31 +60,27 @@ import CodeBlock from '@theme/CodeBlock'; // than those that contain 'English'. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`from "Employees" where +```sql +from "Employees" where search(Notes, "English") or boost(search(Notes, "Italian"), 10) -{"p0":"English","p1":"Italian"} -`} - +``` - - - + -## Boost results - when querying with where clause + - +`boost()` can be used to give different priorities to the results +returned by different `where` clauses. - -{`const companies = await session +```js +const companies = await session // Make a dynamic DocumentQuery on 'Companies' collection .query({ collection: "Companies"}) // Define a 'where' condition @@ -103,22 +103,31 @@ search(Notes, "English") or boost(search(Notes, "Italian"), 10) // Matching documents that start-with 'O' will get the LOWEST scores. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`from "Companies" where +```sql +from "Companies" where boost(startsWith(Name, "O"), 10) or boost(startsWith(Name, "P"), 50) or boost(endsWith(Name, "OP"), 90) -`} - +``` - - - - - + + +### Boost a `whereExists()` condition with Corax + +In RavenDB 7.2.6 and later, when using the Corax search engine, a boosted `whereExists()` condition (`exists()` in RQL) +contributes `1` multiplied by the query boost, rather than a relevance score calculated from the field's values. + +For example, `.whereExists("Fax").boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` +once per matching document, before any index-entry boost is applied. + +The `whereStartsWith()` and `whereEndsWith()` conditions in the example above use relevance-based scoring. +Learn more in [Corax: Scoring](../../../../../indexes/search-engine/corax.mdx#scoring). + + + + diff --git a/docs/client-api/session/querying/text-search/content/_boost-search-results-php.mdx b/docs/client-api/session/querying/text-search/content/_boost-search-results-php.mdx index 8ef3797257..a2a94547ef 100644 --- a/docs/client-api/session/querying/text-search/content/_boost-search-results-php.mdx +++ b/docs/client-api/session/querying/text-search/content/_boost-search-results-php.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -25,21 +27,22 @@ import CodeBlock from '@theme/CodeBlock'; * The calculated score details of the results can be retrieved if needed. Learn more here: [get resulting score](../../../../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) -* In this page: - - * [Boost results - when making a full-text search](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-making-a-full-text-search) - * [Boost results - when querying with where clause](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-querying-with-where-clause) +* In this article: + * [Boost results - when making a full-text search](#boost-results-when-making-a-full-text-search) + * [Boost results - when querying with where clause](#boost-results-when-querying-with-where-clause) + * [Boost a whereExists() condition with Corax](#boost-a-whereexists-condition-with-corax) -## Boost results - when making a full-text search + + To apply boosting while running a full-text search, use the `boost()` method to prioritize the preceding `search()` results. - -{`/** @var array $employees */ +```php +/** @var array $employees */ $employees = $session // Make a dynamic full-text search Query on 'Employees' collection ->query(Employee::class) @@ -58,21 +61,21 @@ $employees = $session // than those that contain 'English'. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`List employees = session.Advanced - // Make a dynamic full-text search DocumentQuery on 'Employees' collection - .DocumentQuery() - // This search predicate will use the default boost value of 1 - .Search(x => x.Notes, "English") - // This search predicate will use a boost value of 10 - .Search(x => x.Notes, "Italian") - // Call 'Boost' to set the boost value of the previous 'Search' call - .Boost(10) - .ToList(); +```php +/** @var array $employees */ +$employees = $session->advanced() + // Make a dynamic full-text search DocumentQuery on 'Employees' collection + ->documentQuery(Employee::class) + // This search predicate will use the default boost value of 1 + ->search("Notes", "English") + // * This search predicate will use a boost value of 10 + ->search("Notes", "Italian") + // Call 'boost()' to set the boost value of the previous 'search()' call + ->boost(10) + ->toList(); // * Results will contain all Employee documents that have // EITHER 'English' OR 'Italian' in their 'Notes' field (case-insensitive). @@ -81,34 +84,32 @@ $employees = $session // than those that contain 'English'. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`from "Employees" where +```sql +from "Employees" where search(Notes, "English") or boost(search(Notes, "Italian"), 10) -`} - +``` + - -## Boost results - when querying with where clause + `boost()` can be used to give different priorities to the results returned by different `where` clauses. - - -{`/** @var array $companies */ + +```php +/** @var array $companies */ $companies = $session->advanced() // Make a dynamic DocumentQuery on 'Companies' collection ->documentQuery(Company::class) // Define a 'Where' condition - ->WhereStartsWith("Name", "O") + ->whereStartsWith("Name", "O") // Call 'Boost' to set the boost value of the previous 'Where' predicate ->boost(10) // Call 'OrElse' so that OR operator will be used between statements @@ -127,20 +128,31 @@ $companies = $session->advanced() // Matching documents that start-with 'O' will get the LOWEST scores. // // * Unless configured otherwise, the resulting documents will be ordered by their score. -`} - +``` - -{`from "Companies" where +```sql +from "Companies" where boost(startsWith(Name, "O"), 10) or boost(startsWith(Name, "P"), 50) or boost(endsWith(Name, "OP"), 90) -`} - +``` - - - + + +### Boost a `whereExists()` condition with Corax + +In RavenDB 7.2.6 and later, when using the Corax search engine, a boosted `whereExists()` condition (`exists()` in RQL) +contributes `1` multiplied by the query boost, rather than a relevance score calculated from the field's values. + +For example, `->whereExists("Fax")->boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` +once per matching document, before any index-entry boost is applied. + +The `whereStartsWith()` and `whereEndsWith()` conditions in the example above use relevance-based scoring. +Learn more in [Corax: Scoring](../../../../../indexes/search-engine/corax.mdx#scoring). + + + + diff --git a/docs/client-api/session/querying/text-search/content/_boost-search-results-python.mdx b/docs/client-api/session/querying/text-search/content/_boost-search-results-python.mdx index 3c3ea9b4c5..6bfdb70688 100644 --- a/docs/client-api/session/querying/text-search/content/_boost-search-results-python.mdx +++ b/docs/client-api/session/querying/text-search/content/_boost-search-results-python.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -25,21 +27,22 @@ import CodeBlock from '@theme/CodeBlock'; * The calculated score details of the results can be retrieved if needed. Learn more here: [get resulting score](../../../../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) -* In this page: - - * [Boost results - when making a full-text search](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-making-a-full-text-search) - * [Boost results - when querying with where clause](../../../../../client-api/session/querying/text-search/boost-search-results.mdx#boost-results---when-querying-with-where-clause) +* In this article: + * [Boost results - when making a full-text search](#boost-results-when-making-a-full-text-search) + * [Boost results - when querying with where clause](#boost-results-when-querying-with-where-clause) + * [Boost a where_exists() condition with Corax](#boost-a-where_exists-condition-with-corax) -## Boost results - when making a full-text search + + To apply boosting while running a full-text search, use the `boost()` method to prioritize the preceding `search()` results. - -{`employees = list( +```python +employees = list( session # Make a dynamic full-text search Query on 'Employees' collection .query(object_type=Employee) @@ -58,29 +61,27 @@ To apply boosting while running a full-text search, use the # before those with 'English'. # # * Search is case-insensitive. -`} - +``` - -{`from "Employees" where +```sql +from "Employees" where search(Notes, "English") or boost(search(Notes, "Italian"), 10) -`} - +``` + - -## Boost results - when querying with where clause + `boost()` can be used to give different priorities to the results returned by different `where` clauses. - -{`companies = list( +```python +companies = list( session.advanced # Make a dynamic DocumentQuery on 'Companies' collection .document_query(object_type=Company) @@ -105,20 +106,31 @@ returned by different `where` clauses. # Matching documents that start-with 'O' will be listed LAST. # # * Search is case-insensitive. -`} - +``` - -{`from "Companies" where +```sql +from "Companies" where boost(startsWith(Name, "O"), 10) or boost(startsWith(Name, "P"), 50) or boost(endsWith(Name, "OP"), 90) -`} - +``` - - - + + +### Boost a `where_exists()` condition with Corax + +In RavenDB 7.2.6 and later, when using the Corax search engine, a boosted `where_exists()` condition (`exists()` in RQL) +contributes `1` multiplied by the query boost, rather than a relevance score calculated from the field's values. + +For example, `.where_exists("Fax").boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` +once per matching document, before any index-entry boost is applied. + +The `where_starts_with()` and `where_ends_with()` conditions in the example above use relevance-based scoring. +Learn more in [Corax: Scoring](../../../../../indexes/search-engine/corax.mdx#scoring). + + + + diff --git a/docs/indexes/boosting.mdx b/docs/indexes/boosting.mdx index 7f4ab6c3b1..1b00b27ed5 100644 --- a/docs/indexes/boosting.mdx +++ b/docs/indexes/boosting.mdx @@ -3,7 +3,7 @@ title: "Indexes: Boosting" sidebar_label: Boosting description: "Boost search relevance in RavenDB indexes by assigning higher weights to specific fields or documents during index definition." sidebar_position: 23 -supported_languages: ["csharp", "java", "php", "nodejs"] +supported_languages: ["csharp", "java", "python", "php", "nodejs"] see_also: - title: "Full-text search" link: "client-api/session/querying/text-search/full-text-search" @@ -36,6 +36,7 @@ import LanguageContent from "@site/src/components/LanguageContent"; import BoostingCsharp from './content/_boosting-csharp.mdx'; import BoostingJava from './content/_boosting-java.mdx'; +import BoostingPython from './content/_boosting-python.mdx'; import BoostingPhp from './content/_boosting-php.mdx'; import BoostingNodejs from './content/_boosting-nodejs.mdx'; @@ -50,6 +51,10 @@ import BoostingNodejs from './content/_boosting-nodejs.mdx'; + + + + diff --git a/docs/indexes/content/_boosting-csharp.mdx b/docs/indexes/content/_boosting-csharp.mdx index 95b737977e..096cf0f099 100644 --- a/docs/indexes/content/_boosting-csharp.mdx +++ b/docs/indexes/content/_boosting-csharp.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -9,9 +11,9 @@ import CodeBlock from '@theme/CodeBlock'; calculated by the underlying engine for each document in the results. * Providing a **boost value** to selected fields allows prioritization of the resulting documents. - The boos value is integrated with the basic score, increasing the document rank. + The boost value is integrated with the basic score, increasing the document rank. -* The automatic ordering of results by their score is [configurable](../../indexes/boosting.mdx#automatic-score-based-ordering). +* The automatic ordering of results by their score is [configurable](#automatic-score-based-ordering). * Boosting can be achieved in the following ways: @@ -21,22 +23,32 @@ import CodeBlock from '@theme/CodeBlock'; * **Via index definition**: By applying a boost factor in the index definition, as described in this article. -* In this page: - * [Assign a boost factor to an index-field](../../indexes/boosting.mdx#assign-a-boost-factor-to-an-index-field) - * [Assign a boost factor to the index-entry](../../indexes/boosting.mdx#assign-a-boost-factor-to-the-index-entry) - * [Automatic score-based ordering](../../indexes/boosting.mdx#automatic-score-based-ordering) - * [Corax vs Lucene: boosting differences](../../indexes/boosting.mdx#automatic-score-based-ordering) +* In this article: + * [Assign a boost factor to an index-field](#assign-a-boost-factor-to-an-index-field) + * [Assign a boost factor to the index-entry](#assign-a-boost-factor-to-the-index-entry) + * [Automatic score-based ordering](#automatic-score-based-ordering) + * [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences) -## Assign a boost factor to an index-field + + Applying a boost value to an index-field allows prioritization of matching documents based on an index-field. + + + +Boosting an index-field is supported only by the **Lucene** search engine. +With **Corax**, only the [index-entry](#assign-a-boost-factor-to-the-index-entry) can be boosted in the index definition. +Learn more in [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences). + + + ##### The index: - -{`public class Orders_ByCountries_BoostByField : AbstractIndexCreationTask +```csharp +public class Orders_ByCountries_BoostByField : AbstractIndexCreationTask { public class IndexEntry { @@ -62,12 +74,11 @@ Applying a boost value to an index-field allows prioritization of matching docum }; } } -`} - +``` - -{`public class Orders_ByCountries_BoostByField_JS : AbstractJavaScriptIndexCreationTask +```csharp +public class Orders_ByCountries_BoostByField_JS : AbstractJavaScriptIndexCreationTask { public Orders_ByCountries_BoostByField_JS() { @@ -83,8 +94,7 @@ Applying a boost value to an index-field allows prioritization of matching docum }; } } -`} - +``` @@ -92,8 +102,8 @@ Applying a boost value to an index-field allows prioritization of matching docum - -{`List orders = session +```csharp +List orders = session // Query the index .Query() .Where(x => x.ShipToCountry == "Poland" || x.CompanyCountry == "Portugal") @@ -103,12 +113,11 @@ Applying a boost value to an index-field allows prioritization of matching docum // Because index-field 'ShipToCountry' was boosted (inside the index definition), // then documents containing 'Poland' in their 'ShipTo.Country' field will get a higher score than // documents containing a company that is located in 'Portugal'. -`} - +``` - -{`List orders = await asyncSession +```csharp +List orders = await asyncSession // Query the index .Query() .Where(x => x.ShipToCountry == "Poland" || x.CompanyCountry == "Portugal") @@ -118,12 +127,11 @@ Applying a boost value to an index-field allows prioritization of matching docum // Because index-field 'ShipToCountry' was boosted (inside the index definition), // then documents containing 'Poland' in their 'ShipTo.Country' field will get a higher score than // documents containing a company that is located in 'Portugal'. -`} - +``` - -{`List orders = session.Advanced +```csharp +List orders = session.Advanced // Query the index .DocumentQuery() .WhereEquals(x => x.ShipToCountry, "Poland") @@ -135,29 +143,28 @@ Applying a boost value to an index-field allows prioritization of matching docum // Because index-field 'ShipToCountry' was boosted (inside the index definition), // then documents containing 'Poland' in their 'ShipTo.Country' field will get a higher score than // documents containing a company that is located in 'Portugal'. -`} - +``` - -{`from index "Orders/ByCountries/BoostByField" +```sql +from index "Orders/ByCountries/BoostByField" where ShipToCountry == "poland" or CompanyCountry == "portugal" -`} - +``` + - -## Assign a boost factor to the index-entry + Applying a boost value to the whole index-entry allows prioritization of matching documents by content from the document. + ##### The index: - -{`public class Orders_ByCountries_BoostByIndexEntry : AbstractIndexCreationTask +```csharp +public class Orders_ByCountries_BoostByIndexEntry : AbstractIndexCreationTask { public class IndexEntry { @@ -182,12 +189,11 @@ Applying a boost value to the whole index-entry allows prioritization of matchin .Boost((float) order.Freight); } } -`} - +``` - -{`public class Orders_ByCountries_BoostByIndexEntry_JS : AbstractJavaScriptIndexCreationTask +```csharp +public class Orders_ByCountries_BoostByIndexEntry_JS : AbstractJavaScriptIndexCreationTask { public Orders_ByCountries_BoostByIndexEntry_JS() { @@ -203,8 +209,7 @@ Applying a boost value to the whole index-entry allows prioritization of matchin }; } } -`} - +``` @@ -212,8 +217,8 @@ Applying a boost value to the whole index-entry allows prioritization of matchin - -{`List orders = session +```csharp +List orders = session // Query the index .Query() .Where(x => x.ShipToCountry == "Poland" || x.CompanyCountry == "Portugal") @@ -222,12 +227,11 @@ Applying a boost value to the whole index-entry allows prioritization of matchin // The resulting score per matching document is affected by the value of the document-field 'Freight'. // Documents with a higher 'Freight' value will rank higher. -`} - +``` - -{`List orders = await asyncSession +```csharp +List orders = await asyncSession // Query the index .Query() .Where(x => x.ShipToCountry == "Poland" || x.CompanyCountry == "Portugal") @@ -236,12 +240,11 @@ Applying a boost value to the whole index-entry allows prioritization of matchin // The resulting score per matching document is affected by the value of the document-field 'Freight'. // Documents with a higher 'Freight' value will rank higher. -`} - +``` - -{`List orders = session.Advanced +```csharp +List orders = session.Advanced // Query the index .DocumentQuery() .WhereEquals(x => x.ShipToCountry, "Poland") @@ -252,21 +255,19 @@ Applying a boost value to the whole index-entry allows prioritization of matchin // The resulting score per matching document is affected by the value of the document-field 'Freight'. // Documents with a higher 'Freight' value will rank higher. -`} - +``` - -{`from index "Orders/ByCountries/BoostByIndexEntry" +```sql +from index "Orders/ByCountries/BoostByIndexEntry" where ShipToCountry == "poland" or CompanyCountry == "portugal" -`} - +``` + - -## Automatic score-based ordering + * By default, whenever boosting is applied, either via dynamic querying or when querying an index that has a boosting factor in its definition, the results will be automatically ordered by the score. @@ -277,22 +278,28 @@ where ShipToCountry == "poland" or CompanyCountry == "portugal" * Refer to the [Get resulting score](../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) section to learn how to retrieve the calculated score of each result. + - -## Corax vs Lucene: boosting differences + * **Boosting features available:** - - * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned - to the [index-entry](../../indexes/boosting.mdx#assign-a-boost-factor-to-the-index-entry). - Applying a boost factor to an _index-field_ is Not supported. - + * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned to the [index-entry](#assign-a-boost-factor-to-the-index-entry). + Applying a boost factor to an _index-field_ is Not supported. * When using **Lucene**, a boost factor can be assigned to both the index-field and the whole index-entry. +--- + * **Algorithm used**: - Corax ranks search results using the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25). - Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. - - - + * Corax uses the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25) to score term-based conditions. + * Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. +--- + +* **Corax scoring for `exists()` and `where true`**: + * In RavenDB 7.2.6 and later, when Corax calculates a score for a query, an `exists()` condition (`WhereExists()` in a `DocumentQuery`) + contributes `1` multiplied by its query boost, once per matching document, regardless of the field's value or number of values. + * For example, `.WhereExists(x => x.Fax).Boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` before any index-entry boost is applied. + * A `where true` condition contributes no score. + * Learn more in [Corax: Scoring](../../indexes/search-engine/corax.mdx#scoring). + + diff --git a/docs/indexes/content/_boosting-java.mdx b/docs/indexes/content/_boosting-java.mdx index 95e8765ded..98c49e3991 100644 --- a/docs/indexes/content/_boosting-java.mdx +++ b/docs/indexes/content/_boosting-java.mdx @@ -2,93 +2,224 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -When querying with some filtering conditions, -a basic score is calculated for each document in the results by the underlying engine. + + +* When querying with some filtering conditions, a basic **score** is + calculated by the underlying engine for each document in the results. + +* Providing a **boost value** to selected fields allows prioritization of the resulting documents. + The boost value is integrated with the basic score, increasing the document rank. + +* The automatic ordering of results by their score is [configurable](#automatic-score-based-ordering). + +* Boosting can be achieved in the following ways: + + * **At query time**: + By applying a boost factor to searched terms at query time (see [Boost search results](../../client-api/session/querying/text-search/boost-search-results.mdx)). + + * **Via index definition**: + By applying a boost factor in the index definition, as described in this article. + +* In this article: + * [Assign a boost factor to an index-field](#assign-a-boost-factor-to-an-index-field) + * [Assign a boost factor to the index-entry](#assign-a-boost-factor-to-the-index-entry) + * [Automatic score-based ordering](#automatic-score-based-ordering) + * [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences) + + + + + +Applying a boost value to an index-field allows prioritization of matching documents based on an index-field. -Providing a **boost value** to some fields allows you to prioritize the resulting documents. -The boost value is integrated with the basic score, making the document rank higher. -Automatic ordering of the results by the score is [configurable](../../indexes/boosting.mdx#automatic-score-based-ordering). + + +Boosting an index-field is supported only by the **Lucene** search engine. +With **Corax**, only the [index-entry](#assign-a-boost-factor-to-the-index-entry) can be boosted in the index definition. +Learn more in [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences). -From the index perspective we can associate to an index entry a boosting factor. -The higher value it has, the more relevant term will be. To do this, we must use the `Boost` method. + -Let's jump straight into the example. -To perform the query that will return employees where either `FirstName` or `LastName` is equal to _Bob_, -and to promote employees (move them to the top of the results) where `FirstName` matches the phrase, we must first create an index with boosted entry. +##### The index: - - -{`public class Employees_ByFirstAndLastName extends AbstractIndexCreationTask { - public Employees_ByFirstAndLastName() { - map = "docs.Employees.Select(employee => new {" + - " FirstName = employee.FirstName.Boost(10)," + - " LastName = employee.LastName" + - "})"; + +```java +public static class Orders_ByCountries_BoostByField + extends AbstractIndexCreationTask { + public Orders_ByCountries_BoostByField() { + // Boost index-field 'ShipToCountry': + // * Use method 'Boost', pass a numeric value to boost by + // * Documents that match the query criteria for this field will rank higher + map = "from order in docs.Orders " + + "let company = LoadDocument(order.Company, \"Companies\") " + + "select new { " + + " ShipToCountry = order.ShipTo.Country.Boost(10), " + + " CompanyCountry = company.Address.Country " + + "}"; } } -`} - +``` - - -{`IndexDefinition indexDefinition = new IndexDefinition(); -indexDefinition.setName("Employees/ByFirstAndLastName"); -indexDefinition.setMaps(Collections.singleton( - "docs.Employees.Select(employee => new {" + - " FirstName = employee.FirstName.Boost(10)," + - " LastName = employee.LastName" + - "})")); - -store.maintenance().send(new PutIndexesOperation(indexDefinition)); -`} - + +```java +public static class Orders_ByCountries_BoostByField_JS + extends AbstractJavaScriptIndexCreationTask { + public Orders_ByCountries_BoostByField_JS() { + setMaps(Sets.newHashSet( + "map('orders', function(order) {" + + " let company = load(order.Company, 'Companies');" + + " return {" + + " ShipToCountry: boost(order.ShipTo.Country, 10)," + + " CompanyCountry: company.Address.Country" + + " };" + + "})")); + } +} +``` -The next step is to perform a query against that index: +##### The query: - - -{`// employees with 'firstName' equal to 'Bob' -// will be higher in results -// than the ones with 'lastName' match -List results = session.query(Employee.class, Employees_ByFirstAndLastName.class) - .whereEquals("FirstName", "Bob") - .whereEquals("LastName", "Bob") + + +```java +List orders = session + // Query the index + .query(Order.class, Orders_ByCountries_BoostByField.class) + .whereEquals("ShipToCountry", "Poland") + .orElse() + .whereEquals("CompanyCountry", "Portugal") .toList(); -`} - + +// Because index-field 'ShipToCountry' was boosted (inside the index definition), +// then documents containing 'Poland' in their 'ShipTo.Country' field +// will get a higher score than documents containing a company +// that is located in 'Portugal'. +``` + + +```sql +from index "Orders/ByCountries/BoostByField" +where ShipToCountry == "poland" or CompanyCountry == "portugal" +``` + -## Remarks + - -Boosting is also available at the query level. - + - +Applying a boost value to the whole index-entry allows prioritization of matching documents by content from the document. -#### Automatic score-based ordering +##### The index: -* By default, whenever boosting is involved, either via a dynamic query or when querying an index that has a boosting factor in its definition, - the results will be automatically ordered by the score. + + +```java +public static class Orders_ByCountries_BoostByIndexEntry + extends AbstractIndexCreationTask { + public Orders_ByCountries_BoostByIndexEntry() { + // Boost the whole index-entry: + // * Use method 'Boost' + // * Pass a document-field that will set the boost level dynamically + // per document indexed. + // * The boost level will vary from one document to another + // based on the value of this field. + map = "from order in docs.Orders " + + "let company = LoadDocument(order.Company, \"Companies\") " + + "select new { " + + " ShipToCountry = order.ShipTo.Country, " + + " CompanyCountry = company.Address.Country " + + "}.Boost((float) order.Freight)"; + } +} +``` + + +```java +public static class Orders_ByCountries_BoostByIndexEntry_JS + extends AbstractJavaScriptIndexCreationTask { + public Orders_ByCountries_BoostByIndexEntry_JS() { + setMaps(Sets.newHashSet( + "map('orders', function(order) {" + + " let company = load(order.Company, 'Companies');" + + " return boost({" + + " ShipToCountry: order.ShipTo.Country," + + " CompanyCountry: company.Address.Country" + + " }, order.Freight);" + + "})")); + } +} +``` + + -* This behavior can be modified using the [OrderByScoreAutomaticallyWhenBoostingIsInvolved](../../server/configuration/indexing-configuration.mdx#indexingorderbyscoreautomaticallywhenboostingisinvolved) - configuration key. +##### The query: - + + +```java +List orders = session + // Query the index + .query(Order.class, Orders_ByCountries_BoostByIndexEntry.class) + .whereEquals("ShipToCountry", "Poland") + .orElse() + .whereEquals("CompanyCountry", "Portugal") + .toList(); - +// The resulting score per matching document is affected by +// the value of the document-field 'Freight'. +// Documents with a higher 'Freight' value will rank higher. +``` + + +```sql +from index "Orders/ByCountries/BoostByIndexEntry" +where ShipToCountry == "poland" or CompanyCountry == "portugal" +``` + + -When using [Corax](../../indexes/search-engine/corax.mdx) as the search engine: + -* [indexing-time boosting](../../indexes/search-engine/corax.mdx#supported-features) - is available for documents, but not for document fields. -* Corax ranks search results using the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25). - Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. + - +* By default, whenever boosting is applied, either via dynamic querying or when querying an index + that has a boosting factor in its definition, the results will be automatically ordered by the score. + +* This behavior can be modified using the [OrderByScoreAutomaticallyWhenBoostingIsInvolved](../../server/configuration/indexing-configuration.mdx#indexingorderbyscoreautomaticallywhenboostingisinvolved) + configuration key. + +* Refer to the [Get resulting score](../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) + section to learn how to retrieve the calculated score of each result. + + + + + +* **Boosting features available:** + * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned to the [index-entry](#assign-a-boost-factor-to-the-index-entry). + Applying a boost factor to an _index-field_ is Not supported. + * When using **Lucene**, a boost factor can be assigned to both the index-field and the whole index-entry. + +--- + +* **Algorithm used**: + * Corax uses the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25) to score term-based conditions. + * Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. +--- + +* **Corax scoring for `exists()` and `where true`**: + * In RavenDB 7.2.6 and later, when Corax calculates a score for a query, an `exists()` condition (`whereExists()` in the Java client) + contributes `1` multiplied by its query boost, once per matching document, regardless of the field's value or number of values. + * For example, `.whereExists("Fax").boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` before any index-entry boost is applied. + * A `where true` condition contributes no score. + * Learn more in [Corax: Scoring](../../indexes/search-engine/corax.mdx#scoring). + diff --git a/docs/indexes/content/_boosting-nodejs.mdx b/docs/indexes/content/_boosting-nodejs.mdx index 6211954a3c..480914d951 100644 --- a/docs/indexes/content/_boosting-nodejs.mdx +++ b/docs/indexes/content/_boosting-nodejs.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -9,9 +11,9 @@ import CodeBlock from '@theme/CodeBlock'; calculated by the underlying engine for each document in the results. * Providing a **boost value** to selected fields allows prioritization of the resulting documents. - The boos value is integrated with the basic score, increasing the document rank. + The boost value is integrated with the basic score, increasing the document rank. -* The automatic ordering of results by their score is [configurable](../../indexes/boosting.mdx#automatic-score-based-ordering). +* The automatic ordering of results by their score is [configurable](#automatic-score-based-ordering). * Boosting can be achieved in the following ways: @@ -21,27 +23,36 @@ import CodeBlock from '@theme/CodeBlock'; * **Via index definition**: By applying a boost factor in the index definition, as described in this article. -* In this page: - * [Assign a boost factor to an index-field](../../indexes/boosting.mdx#assign-a-boost-factor-to-an-index-field) - * [Assign a boost factor to the index-entry](../../indexes/boosting.mdx#assign-a-boost-factor-to-the-index-entry) - * [Automatic score-based ordering](../../indexes/boosting.mdx#automatic-score-based-ordering) - * [Corax vs Lucene: boosting differences](../../indexes/boosting.mdx#automatic-score-based-ordering) +* In this article: + * [Assign a boost factor to an index-field](#assign-a-boost-factor-to-an-index-field) + * [Assign a boost factor to the index-entry](#assign-a-boost-factor-to-the-index-entry) + * [Automatic score-based ordering](#automatic-score-based-ordering) + * [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences) -## Assign a boost factor to an index-field + + Applying a boost value to an index-field allows prioritization of matching documents based on an index-field. + + + +Boosting an index-field is supported only by the **Lucene** search engine. +With **Corax**, only the [index-entry](#assign-a-boost-factor-to-the-index-entry) can be boosted in the index definition. +Learn more in [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences). + + + ##### The index: - - -{`class Orders_ByCountries_BoostByField extends AbstractCsharpIndexCreationTask \{ - constructor() \{ +```js +class Orders_ByCountries_BoostByField extends AbstractCsharpIndexCreationTask { + constructor() { super(); - this.map = \`from order in docs.Orders + this.map = `from order in docs.Orders let company = LoadDocument(order.Company, "Companies") - select new \{ + select new { // Boost index-field 'ShipToCountry': // * Use method 'Boost', pass a numeric value to boost by @@ -49,19 +60,17 @@ Applying a boost value to an index-field allows prioritization of matching docum ShipToCountry = order.ShipTo.Country.Boost(10), CompanyCountry = company.Address.Country - \}\`; - \} -\} -`} - - + }`; + } +} +``` ##### The query: - -{`const orders = await session +```js +const orders = await session .query({ indexName: "Orders/ByCountries/BoostByField" }) .whereEquals("ShipToCountry", "Poland") .orElse() @@ -69,81 +78,79 @@ Applying a boost value to an index-field allows prioritization of matching docum .all(); // Because index-field 'ShipToCountry' was boosted (inside the index definition), -// then documents containing 'Poland' in their 'ShipTo.Country' field will get a higher score than -// documents containing a company that is located in 'Portugal'. -`} - +// then documents containing 'Poland' in their 'ShipTo.Country' field +// will get a higher score than documents containing a company +// that is located in 'Portugal'. +``` - -{`from index "Orders/ByCountries/BoostByField" +```sql +from index "Orders/ByCountries/BoostByField" where ShipToCountry == "poland" or CompanyCountry == "portugal" -`} - +``` + - -## Assign a boost factor to the index-entry + Applying a boost value to the whole index-entry allows prioritization of matching documents by content from the document. + ##### The index: - - -{`class Orders_ByCountries_BoostByIndexEntry extends AbstractCsharpIndexCreationTask \{ - constructor() \{ +```js +class Orders_ByCountries_BoostByIndexEntry extends AbstractCsharpIndexCreationTask { + constructor() { super(); - this.map = \`from order in docs.Orders + this.map = `from order in docs.Orders let company = LoadDocument(order.Company, "Companies") - select new \{ + select new { ShipToCountry = order.ShipTo.Country, CompanyCountry = company.Address.Country - \} + } // Boost the whole index-entry: // * Use method 'Boost' - // * Pass a document-field that will set the boost level dynamically per document indexed. - // * The boost level will vary from one document to another based on the value of this field. + // * Pass a document-field that will set the boost level dynamically + // per document indexed. + // * The boost level will vary from one document to another + // based on the value of this field. - .Boost(order.Freight)\`; - \} -\} -`} - - + .Boost(order.Freight)`; + } +} +``` ##### The query: - -{`const orders = await session +```js +const orders = await session .query({ indexName: "Orders/ByCountries/BoostByIndexEntry" }) .whereEquals("ShipToCountry", "Poland") .orElse() .whereEquals("CompanyCountry", "Portugal") .all(); -// The resulting score per matching document is affected by the value of the document-field 'Freight'. +// The resulting score per matching document is affected by +// the value of the document-field 'Freight'. // Documents with a higher 'Freight' value will rank higher. -`} - +``` - -{`from index "Orders/ByCountries/BoostByIndexEntry" +```sql +from index "Orders/ByCountries/BoostByIndexEntry" where ShipToCountry == "poland" or CompanyCountry == "portugal" -`} - +``` + - -## Automatic score-based ordering + * By default, whenever boosting is applied, either via dynamic querying or when querying an index that has a boosting factor in its definition, the results will be automatically ordered by the score. @@ -154,21 +161,28 @@ where ShipToCountry == "poland" or CompanyCountry == "portugal" * Refer to the [Get resulting score](../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) section to learn how to retrieve the calculated score of each result. + + -## Corax vs Lucene: boosting differences - -* **Boosting features available:** - - * When using **Corax** as the underlying indexing engine, you can only [assign a boost factor to the index-entry](../../indexes/boosting.mdx#assign-a-boost-factor-to-the-index-entry). - Applying a boost factor to an index-field is Not supported. - - * When using **Lucene**, you can assign a boost factor to both the index-field and the whole index-entry. +* **Boosting features available:** + * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned to the [index-entry](#assign-a-boost-factor-to-the-index-entry). + Applying a boost factor to an _index-field_ is Not supported. + * When using **Lucene**, a boost factor can be assigned to both the index-field and the whole index-entry. +--- + * **Algorithm used**: - Corax ranks search results using the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25). - Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. - - - - + * Corax uses the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25) to score term-based conditions. + * Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. + +--- + +* **Corax scoring for `exists()` and `where true`**: + * In RavenDB 7.2.6 and later, when Corax calculates a score for a query, an `exists()` condition (`whereExists()` in the Node.js client) + contributes `1` multiplied by its query boost, once per matching document, regardless of the field's value or number of values. + * For example, `.whereExists("Fax").boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` before any index-entry boost is applied. + * A `where true` condition contributes no score. + * Learn more in [Corax: Scoring](../../indexes/search-engine/corax.mdx#scoring). + + diff --git a/docs/indexes/content/_boosting-php.mdx b/docs/indexes/content/_boosting-php.mdx index 86091e0857..b1a1221a85 100644 --- a/docs/indexes/content/_boosting-php.mdx +++ b/docs/indexes/content/_boosting-php.mdx @@ -2,6 +2,8 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; @@ -9,9 +11,9 @@ import CodeBlock from '@theme/CodeBlock'; calculated by the underlying engine for each document in the results. * Providing a **boost value** to selected fields allows prioritization of the resulting documents. - The boos value is integrated with the basic score, increasing the document rank. + The boost value is integrated with the basic score, increasing the document rank. -* The automatic ordering of results by their score is [configurable](../../indexes/boosting.mdx#automatic-score-based-ordering). +* The automatic ordering of results by their score is [configurable](#automatic-score-based-ordering). * Boosting can be achieved in the following ways: @@ -21,22 +23,32 @@ import CodeBlock from '@theme/CodeBlock'; * **Via index definition**: By applying a boost factor in the index definition, as described in this article. -* In this page: - * [Assign a boost factor to an index-field](../../indexes/boosting.mdx#assign-a-boost-factor-to-an-index-field) - * [Assign a boost factor to the index-entry](../../indexes/boosting.mdx#assign-a-boost-factor-to-the-index-entry) - * [Automatic score-based ordering](../../indexes/boosting.mdx#automatic-score-based-ordering) - * [Corax vs Lucene: boosting differences](../../indexes/boosting.mdx#automatic-score-based-ordering) +* In this article: + * [Assign a boost factor to an index-field](#assign-a-boost-factor-to-an-index-field) + * [Assign a boost factor to the index-entry](#assign-a-boost-factor-to-the-index-entry) + * [Automatic score-based ordering](#automatic-score-based-ordering) + * [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences) -## Assign a boost factor to an index-field + + Applying a boost value to an index-field allows prioritization of matching documents based on an index-field. + + + +Boosting an index-field is supported only by the **Lucene** search engine. +With **Corax**, only the [index-entry](#assign-a-boost-factor-to-the-index-entry) can be boosted in the index definition. +Learn more in [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences). + + + ##### The index: - -{`class Orders_ByCountries_BoostByField_IndexEntry +```php +class Orders_ByCountries_BoostByField_IndexEntry { // Index-field 'ShipToCountry' will be boosted in the map definition below public ?string $shipToCountry = null; @@ -75,32 +87,31 @@ class Orders_ByCountries_BoostByField extends AbstractIndexCreationTask $this->map = "docs.Orders.Select(order => new { " . " ShipToCountry = order.ShipTo.Country.Boost(10), " . - " CompanyCountry = this.LoadDocument(order.Company, \\"Companies\\").Address.Country " . + " CompanyCountry = this.LoadDocument(order.Company, \"Companies\")" . + ".Address.Country " . "})"; } } -`} - +``` - -{`class Orders_ByCountries_BoostByField_JS extends AbstractJavaScriptIndexCreationTask +```php +class Orders_ByCountries_BoostByField_JS extends AbstractJavaScriptIndexCreationTask { public function __construct() { parent::__construct(); - $this->setMaps(["map('Orders', function (order) {\\n" . - " let company = load(order.Company, 'Companies')\\n" . - " return {\\n" . - " ShipToCountry: boost(order.ShipTo.Country, 10),\\n" . - " CompanyCountry: company.Address.Country\\n" . - " }\\n" . + $this->setMaps(["map('Orders', function (order) {\n" . + " let company = load(order.Company, 'Companies')\n" . + " return {\n" . + " ShipToCountry: boost(order.ShipTo.Country, 10),\n" . + " CompanyCountry: company.Address.Country\n" . + " }\n" . "})"]); } } -`} - +``` @@ -108,10 +119,13 @@ class Orders_ByCountries_BoostByField extends AbstractIndexCreationTask - -{`$orders = $session +```php +$orders = $session // Query the index - ->query(Orders_ByCountries_BoostByField_IndexEntry::class, Orders_ByCountries_BoostByField::class) + ->query( + Orders_ByCountries_BoostByField_IndexEntry::class, + Orders_ByCountries_BoostByField::class + ) ->whereEquals("ShipToCountry", "Poland") ->orElse() ->whereEquals("CompanyCountry", "Portugal") @@ -119,16 +133,19 @@ class Orders_ByCountries_BoostByField extends AbstractIndexCreationTask ->toList(); // Because index-field 'ShipToCountry' was boosted (inside the index definition), -// then documents containing 'Poland' in their 'ShipTo.Country' field will get a higher score than -// documents containing a company that is located in 'Portugal'. -`} - +// then documents containing 'Poland' in their 'ShipTo.Country' field +// will get a higher score than documents containing a company +// that is located in 'Portugal'. +``` - -{`$orders = $session->advanced() +```php +$orders = $session->advanced() // Query the index - ->documentQuery(Orders_ByCountries_BoostByField_IndexEntry::class, Orders_ByCountries_BoostByField::class) + ->documentQuery( + Orders_ByCountries_BoostByField_IndexEntry::class, + Orders_ByCountries_BoostByField::class + ) ->whereEquals("ShipToCountry", "Poland") ->orElse() ->whereEquals("CompanyCountry", "Portugal") @@ -136,31 +153,31 @@ class Orders_ByCountries_BoostByField extends AbstractIndexCreationTask ->toList(); // Because index-field 'ShipToCountry' was boosted (inside the index definition), -// then documents containing 'Poland' in their 'ShipTo.Country' field will get a higher score than -// documents containing a company that is located in 'Portugal'. -`} - +// then documents containing 'Poland' in their 'ShipTo.Country' field +// will get a higher score than documents containing a company +// that is located in 'Portugal'. +``` - -{`from index "Orders/ByCountries/BoostByField" +```sql +from index "Orders/ByCountries/BoostByField" where ShipToCountry == "poland" or CompanyCountry == "portugal" -`} - +``` + - -## Assign a boost factor to the index-entry + Applying a boost value to the whole index-entry allows prioritization of matching documents by content from the document. + ##### The index: - -{`class Orders_ByCountries_BoostByIndexEntry_IndexEntry +```php +class Orders_ByCountries_BoostByIndexEntry_IndexEntry { public ?string $shipToCountry = null; public ?string $companyCountry = null; @@ -194,39 +211,40 @@ class Orders_ByCountries_BoostByIndexEntry extends AbstractIndexCreationTask // Boost the whole index-entry: // * Use method 'Boost' - // * Pass a document-field that will set the boost level dynamically per document indexed. - // * The boost level will vary from one document to another based on the value of this field. + // * Pass a document-field that will set the boost level dynamically + // per document indexed. + // * The boost level will vary from one document to another + // based on the value of this field. $this->map = "docs.Orders.Select(order => new { " . " ShipToCountry = order.ShipTo.Country, " . - " CompanyCountry = this.LoadDocument(order.Company, \\"Companies\\").Address.Country " . + " CompanyCountry = this.LoadDocument(order.Company, \"Companies\")" . + ".Address.Country " . "}.Boost((float) order.Freight))"; } } -`} - +``` - -{`class Orders_ByCountries_BoostByIndexEntry_JS extends AbstractJavaScriptIndexCreationTask +```php +class Orders_ByCountries_BoostByIndexEntry_JS extends AbstractJavaScriptIndexCreationTask { public function __construct() { parent::__construct(); - $this->setMaps(["map('Orders', function (order) {\\n" . - " let company = load(order.Company, 'Companies')\\n" . - " return boost({\\n" . - " ShipToCountry: order.ShipTo.Country,\\n" . - " CompanyCountry: company.Address.Country\\n" . - " }, order.Freight)\\n" . + $this->setMaps(["map('Orders', function (order) {\n" . + " let company = load(order.Company, 'Companies')\n" . + " return boost({\n" . + " ShipToCountry: order.ShipTo.Country,\n" . + " CompanyCountry: company.Address.Country\n" . + " }, order.Freight)\n" . "})"]); } } -`} - +``` @@ -234,49 +252,54 @@ class Orders_ByCountries_BoostByIndexEntry extends AbstractIndexCreationTask - -{`$orders = $session +```php +$orders = $session // Query the index - ->query(Orders_ByCountries_BoostByIndexEntry_IndexEntry::class, Orders_ByCountries_BoostByIndexEntry::class) + ->query( + Orders_ByCountries_BoostByIndexEntry_IndexEntry::class, + Orders_ByCountries_BoostByIndexEntry::class + ) ->whereEquals("ShipToCountry", "Poland") ->orElse() ->whereEquals("CompanyCountry", "Portugal") ->ofType(Order::class) ->toList(); -// The resulting score per matching document is affected by the value of the document-field 'Freight'. +// The resulting score per matching document is affected by +// the value of the document-field 'Freight'. // Documents with a higher 'Freight' value will rank higher. -`} - +``` - -{`$orders = $session->advanced() +```php +$orders = $session->advanced() // Query the index - ->documentQuery(Orders_ByCountries_BoostByIndexEntry_IndexEntry::class, Orders_ByCountries_BoostByIndexEntry::class) + ->documentQuery( + Orders_ByCountries_BoostByIndexEntry_IndexEntry::class, + Orders_ByCountries_BoostByIndexEntry::class + ) ->whereEquals("ShipToCountry", "Poland") ->orElse() ->whereEquals("CompanyCountry", "Portugal") ->ofType(Order::class) ->toList(); -// The resulting score per matching document is affected by the value of the document-field 'Freight'. +// The resulting score per matching document is affected by +// the value of the document-field 'Freight'. // Documents with a higher 'Freight' value will rank higher. -`} - +``` - -{`from index "Orders/ByCountries/BoostByIndexEntry" +```sql +from index "Orders/ByCountries/BoostByIndexEntry" where ShipToCountry == "poland" or CompanyCountry == "portugal" -`} - +``` + - -## Automatic score-based ordering + * By default, whenever boosting is applied, either via dynamic querying or when querying an index that has a boosting factor in its definition, the results will be automatically ordered by the score. @@ -287,22 +310,28 @@ where ShipToCountry == "poland" or CompanyCountry == "portugal" * Refer to the [Get resulting score](../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) section to learn how to retrieve the calculated score of each result. + - -## Corax vs Lucene: boosting differences + * **Boosting features available:** - - * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned - to the [index-entry](../../indexes/boosting.mdx#assign-a-boost-factor-to-the-index-entry). - Applying a boost factor to an _index-field_ is Not supported. - + * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned to the [index-entry](#assign-a-boost-factor-to-the-index-entry). + Applying a boost factor to an _index-field_ is Not supported. * When using **Lucene**, a boost factor can be assigned to both the index-field and the whole index-entry. +--- + * **Algorithm used**: - Corax ranks search results using the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25). - Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. - - - - + * Corax uses the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25) to score term-based conditions. + * Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. + +--- + +* **Corax scoring for `exists()` and `where true`**: + * In RavenDB 7.2.6 and later, when Corax calculates a score for a query, an `exists()` condition (`whereExists()` in the PHP client) + contributes `1` multiplied by its query boost, once per matching document, regardless of the field's value or number of values. + * For example, `->whereExists("Fax")->boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` before any index-entry boost is applied. + * A `where true` condition contributes no score. + * Learn more in [Corax: Scoring](../../indexes/search-engine/corax.mdx#scoring). + + diff --git a/docs/indexes/content/_boosting-python.mdx b/docs/indexes/content/_boosting-python.mdx new file mode 100644 index 0000000000..3fbdf650ee --- /dev/null +++ b/docs/indexes/content/_boosting-python.mdx @@ -0,0 +1,243 @@ +import Admonition from '@theme/Admonition'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; + + + +* When querying with some filtering conditions, a basic **score** is + calculated by the underlying engine for each document in the results. + +* Providing a **boost value** to selected fields allows prioritization of the resulting documents. + The boost value is integrated with the basic score, increasing the document rank. + +* The automatic ordering of results by their score is [configurable](#automatic-score-based-ordering). + +* Boosting can be achieved in the following ways: + + * **At query time**: + By applying a boost factor to searched terms at query time (see [Boost search results](../../client-api/session/querying/text-search/boost-search-results.mdx)). + + * **Via index definition**: + By applying a boost factor in the index definition, as described in this article. + +* In this article: + * [Assign a boost factor to an index-field](#assign-a-boost-factor-to-an-index-field) + * [Assign a boost factor to the index-entry](#assign-a-boost-factor-to-the-index-entry) + * [Automatic score-based ordering](#automatic-score-based-ordering) + * [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences) + + + + + +Applying a boost value to an index-field allows prioritization of matching documents based on an index-field. + + + +Boosting an index-field is supported only by the **Lucene** search engine. +With **Corax**, only the [index-entry](#assign-a-boost-factor-to-the-index-entry) can be boosted in the index definition. +Learn more in [Corax vs Lucene: boosting differences](#corax-vs-lucene-boosting-differences). + + + +##### The index: + + + +```python +class Orders_ByCountries_BoostByField(AbstractIndexCreationTask): + class IndexEntry: + def __init__(self, ShipToCountry: str = None, CompanyCountry: str = None): + # Index-field 'ShipToCountry' will be boosted in the map definition below + self.ShipToCountry = ShipToCountry + self.CompanyCountry = CompanyCountry + + def __init__(self): + super().__init__() + # Boost index-field 'ShipToCountry': + # * Use method 'Boost', pass a numeric value to boost by + # * Documents that match the query criteria for this field will rank higher + self.map = ( + "from order in docs.Orders " + 'let company = LoadDocument(order.Company, "Companies") ' + "select new { " + " ShipToCountry = order.ShipTo.Country.Boost(10), " + " CompanyCountry = company.Address.Country " + "}" + ) +``` + + +```python +class Orders_ByCountries_BoostByField_JS(AbstractJavaScriptIndexCreationTask): + def __init__(self): + super().__init__() + self.maps = { + """ + map('orders', function(order) { + let company = load(order.Company, 'Companies') + return { + ShipToCountry: boost(order.ShipTo.Country, 10), + CompanyCountry: company.Address.Country + }; + }) + """ + } +``` + + + +##### The query: + + + +```python +orders = list( + session.query_index_type( + Orders_ByCountries_BoostByField, Orders_ByCountries_BoostByField.IndexEntry + ) + .where_equals("ShipToCountry", "Poland") + .or_else() + .where_equals("CompanyCountry", "Portugal") + .of_type(Order) +) + +# Because index-field 'ShipToCountry' was boosted (inside the index definition), +# then documents containing 'Poland' in their 'ShipTo.Country' field +# will get a higher score than documents containing a company +# that is located in 'Portugal'. +``` + + +```sql +from index "Orders/ByCountries/BoostByField" +where ShipToCountry == "poland" or CompanyCountry == "portugal" +``` + + + + + + + +Applying a boost value to the whole index-entry allows prioritization of matching documents by content from the document. + +##### The index: + + + +```python +class Orders_ByCountries_BoostByIndexEntry(AbstractIndexCreationTask): + class IndexEntry: + def __init__(self, ShipToCountry: str = None, CompanyCountry: str = None): + self.ShipToCountry = ShipToCountry + self.CompanyCountry = CompanyCountry + + def __init__(self): + super().__init__() + # Boost the whole index-entry: + # * Use method 'Boost' + # * Pass a document-field that will set the boost level dynamically + # per document indexed. + # * The boost level will vary from one document to another + # based on the value of this field. + self.map = ( + "from order in docs.Orders " + 'let company = LoadDocument(order.Company, "Companies") ' + "select new { " + " ShipToCountry = order.ShipTo.Country, " + " CompanyCountry = company.Address.Country " + "}.Boost((float) order.Freight)" + ) +``` + + +```python +class Orders_ByCountries_BoostByIndexEntry_JS(AbstractJavaScriptIndexCreationTask): + def __init__(self): + super().__init__() + self.maps = { + """ + map('orders', function(order) { + let company = load(order.Company, 'Companies') + return boost({ + ShipToCountry: order.ShipTo.Country, + CompanyCountry: company.Address.Country + }, order.Freight) + }) + """ + } +``` + + + +##### The query: + + + +```python +orders = list( + session.query_index_type( + Orders_ByCountries_BoostByIndexEntry, + Orders_ByCountries_BoostByIndexEntry.IndexEntry, + ) + .where_equals("ShipToCountry", "Poland") + .or_else() + .where_equals("CompanyCountry", "Portugal") + .of_type(Order) +) + +# The resulting score per matching document is affected by +# the value of the document-field 'Freight'. +# Documents with a higher 'Freight' value will rank higher. +``` + + +```sql +from index "Orders/ByCountries/BoostByIndexEntry" +where ShipToCountry == "poland" or CompanyCountry == "portugal" +``` + + + + + + + +* By default, whenever boosting is applied, either via dynamic querying or when querying an index + that has a boosting factor in its definition, the results will be automatically ordered by the score. + +* This behavior can be modified using the [OrderByScoreAutomaticallyWhenBoostingIsInvolved](../../server/configuration/indexing-configuration.mdx#indexingorderbyscoreautomaticallywhenboostingisinvolved) + configuration key. + +* Refer to the [Get resulting score](../../querying/sorting-query-results/sort-query-results.mdx#get-resulting-score) + section to learn how to retrieve the calculated score of each result. + + + + + +* **Boosting features available:** + * When using **Corax** as the underlying indexing engine, a boost factor can only be assigned to the [index-entry](#assign-a-boost-factor-to-the-index-entry). + Applying a boost factor to an _index-field_ is Not supported. + * When using **Lucene**, a boost factor can be assigned to both the index-field and the whole index-entry. + +--- + +* **Algorithm used**: + * Corax uses the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25) to score term-based conditions. + * Other search engines, e.g. Lucene, may use a different ranking algorithm and return different search results. + +--- + +* **Corax scoring for `exists()` and `where true`**: + * In RavenDB 7.2.6 and later, when Corax calculates a score for a query, an `exists()` condition (`where_exists()` in the Python client) + contributes `1` multiplied by its query boost, once per matching document, regardless of the field's value or number of values. + * For example, `.where_exists("Fax").boost(3)` (`boost(exists(Fax), 3)` in RQL) contributes `3` before any index-entry boost is applied. + * A `where true` condition contributes no score. + * Learn more in [Corax: Scoring](../../indexes/search-engine/corax.mdx#scoring). + + diff --git a/docs/indexes/search-engine/corax.mdx b/docs/indexes/search-engine/corax.mdx index 7c354c5a29..df0c63a98d 100644 --- a/docs/indexes/search-engine/corax.mdx +++ b/docs/indexes/search-engine/corax.mdx @@ -46,6 +46,7 @@ import Panel from '@site/src/components/Panel'; * [Per database](../../indexes/search-engine/corax.mdx#select-search-engine-per-database) * [Per static index](../../indexes/search-engine/corax.mdx#select-search-engine-per-static-index) * [Unsupported features](../../indexes/search-engine/corax.mdx#unsupported-features) + * [Scoring](../../indexes/search-engine/corax.mdx#scoring) * [Handling complex JSON objects](../../indexes/search-engine/corax.mdx#handling-complex-json-objects) * [Compound fields](../../indexes/search-engine/corax.mdx#compound-fields) * [Limits](../../indexes/search-engine/corax.mdx#limits) @@ -269,6 +270,48 @@ If the `Orders/ByCompany` index uses Corax, running this query will fail. + + +* Corax calculates scores in any of the following cases: + * The query orders by `score()`. + * The query uses [`boost()`](../../client-api/session/querying/text-search/boost-search-results.mdx). + * The queried index boosts index entries. + * The query uses vector search. + + By default, when the query specifies no other ordering, RavenDB orders scored results by score. + For term-based conditions, such as equality, `search()`, and `startsWith()`, + Corax uses the [BM25 algorithm](https://en.wikipedia.org/wiki/Okapi_BM25) to calculate relevance. + +* **Existence checks add a constant score**: + + * **Before RavenDB 7.2.6**, + a scored `exists()` condition used BM25 relevance calculated for each distinct field value. + + * **In RavenDB 7.2.6 and later**, + a scored `exists()` condition contributes `1` multiplied by its query boost once per matching document, regardless of the field's value or number of values. + For example, `boost(exists(Fax), 3)` contributes `3` before any index-entry boost is applied. + This change does not affect which documents match, but it can change `@index-score` values and score-based ordering compared with earlier versions. + +* **`where true` adds no score**: + A `where true` condition matches all documents and adds nothing to their score. + +* **Effect on ranking**: + + * An optional `exists()` condition in an `or` adds to the score of documents that contain the field, + but not to the score of documents that do not. + + * A required `exists()` condition in an `and` adds the same constant to every result. + Without index-entry boosting, it does not change their relative order. + Different index-entry boosts can change that order because each document's index-entry boost multiplies its combined score. + +* **Performance**: + When scoring is required, Corax scores `exists()` matches in batches instead of calculating BM25 relevance for each distinct field value. + This improves performance, especially for fields with many distinct values, such as IDs or email addresses. + +* Learn more about boosting with Corax in [Corax vs Lucene: boosting differences](../../indexes/boosting.mdx#corax-vs-lucene-boosting-differences). + + + @@ -805,4 +848,4 @@ Common Corax configuration options include: For the full list of indexing configuration options, see [Indexing configuration](../../server/configuration/indexing-configuration.mdx). - \ No newline at end of file + diff --git a/docs/querying/rql/what-is-rql.mdx b/docs/querying/rql/what-is-rql.mdx index 11b9700ed2..51e25214f6 100644 --- a/docs/querying/rql/what-is-rql.mdx +++ b/docs/querying/rql/what-is-rql.mdx @@ -361,6 +361,11 @@ where exists(Name) and NOT Name in ("The Big Cheese", "The Cracker Box") Avoid using `where true` or an `exists()` check on a *different* field. If a document is missing the field you're filtering on, these anchors may return unexpected results. +In RavenDB 7.2.6 and later, when ordering by score with the Corax search engine, +the `exists()` and `where true` conditions contribute differently: +`exists()` adds a constant score, while `where true` adds no score. +Learn more in [Corax: Scoring](../../indexes/search-engine/corax.mdx#scoring). + diff --git a/docs/querying/sorting-query-results/content/_sort-query-results-csharp.mdx b/docs/querying/sorting-query-results/content/_sort-query-results-csharp.mdx index 6d4ee3a16d..e00a460605 100644 --- a/docs/querying/sorting-query-results/content/_sort-query-results-csharp.mdx +++ b/docs/querying/sorting-query-results/content/_sort-query-results-csharp.mdx @@ -704,6 +704,18 @@ order by score() + + +#### Scoring with Corax + +* Not every condition uses relevance-based scoring. + In **RavenDB 7.2.6 and later**, when using the Corax search engine, an `exists()` condition + (`WhereExists()` in a `DocumentQuery`) contributes a constant score to each matching document. + A `where true` condition contributes no score. +* Learn more in [Corax: Scoring](../../../indexes/search-engine/corax.mdx#scoring). + + + #### Get resulting score: @@ -1362,4 +1374,4 @@ public enum NullsOrdering | **sorterName** | `string` | The name of your custom sorter class | | **nulls** | `NullsOrdering` | Per-clause placement of `null` / missing values ([Corax](../../../indexes/search-engine/corax.mdx) only):
`NullsOrdering.Default` (use configured default)
`NullsOrdering.First` (nulls before non-nulls)
`NullsOrdering.Last` (nulls after non-nulls)
Direction-independent: behavior is the same under `ASC` and `DESC`. | - \ No newline at end of file + diff --git a/docs/querying/sorting-query-results/content/_sort-query-results-java.mdx b/docs/querying/sorting-query-results/content/_sort-query-results-java.mdx index f4f6e28ab8..dae8a4edb0 100644 --- a/docs/querying/sorting-query-results/content/_sort-query-results-java.mdx +++ b/docs/querying/sorting-query-results/content/_sort-query-results-java.mdx @@ -453,6 +453,18 @@ order by score() + + +#### Scoring with Corax + +* Not every condition uses relevance-based scoring. + In **RavenDB 7.2.6 and later**, when using the Corax search engine, an `exists()` condition + (`whereExists()` in the Java client) contributes a constant score to each matching document. + A `where true` condition contributes no score. +* Learn more in [Corax: Scoring](../../../indexes/search-engine/corax.mdx#scoring). + + + #### Get resulting score: diff --git a/docs/querying/sorting-query-results/content/_sort-query-results-nodejs.mdx b/docs/querying/sorting-query-results/content/_sort-query-results-nodejs.mdx index c64d5fadf9..16659bdfe6 100644 --- a/docs/querying/sorting-query-results/content/_sort-query-results-nodejs.mdx +++ b/docs/querying/sorting-query-results/content/_sort-query-results-nodejs.mdx @@ -467,6 +467,18 @@ order by score() + + +#### Scoring with Corax + +* Not every condition uses relevance-based scoring. + In **RavenDB 7.2.6 and later**, when using the Corax search engine, an `exists()` condition + (`whereExists()` in the Node.js client) contributes a constant score to each matching document. + A `where true` condition contributes no score. +* Learn more in [Corax: Scoring](../../../indexes/search-engine/corax.mdx#scoring). + + + #### Get resulting score: diff --git a/docs/querying/sorting-query-results/content/_sort-query-results-php.mdx b/docs/querying/sorting-query-results/content/_sort-query-results-php.mdx index 74a2aaab49..2ab19f6f20 100644 --- a/docs/querying/sorting-query-results/content/_sort-query-results-php.mdx +++ b/docs/querying/sorting-query-results/content/_sort-query-results-php.mdx @@ -429,6 +429,18 @@ order by score() + + +#### Scoring with Corax + +* Not every condition uses relevance-based scoring. + In **RavenDB 7.2.6 and later**, when using the Corax search engine, an `exists()` condition + (`whereExists()` in the PHP client) contributes a constant score to each matching document. + A `where true` condition contributes no score. +* Learn more in [Corax: Scoring](../../../indexes/search-engine/corax.mdx#scoring). + + + #### Get resulting score: diff --git a/docs/querying/sorting-query-results/content/_sort-query-results-python.mdx b/docs/querying/sorting-query-results/content/_sort-query-results-python.mdx index 92ec1c55c2..36b4432363 100644 --- a/docs/querying/sorting-query-results/content/_sort-query-results-python.mdx +++ b/docs/querying/sorting-query-results/content/_sort-query-results-python.mdx @@ -474,6 +474,18 @@ order by score() + + +#### Scoring with Corax + +* Not every condition uses relevance-based scoring. + In **RavenDB 7.2.6 and later**, when using the Corax search engine, an `exists()` condition + (`where_exists()` in the Python client) contributes a constant score to each matching document. + A `where true` condition contributes no score. +* Learn more in [Corax: Scoring](../../../indexes/search-engine/corax.mdx#scoring). + + + #### Get resulting score: @@ -507,9 +519,9 @@ The score details can be retrieved by either: employees = list( session.query(object_type=Employee) - .search("notes", "English") + .search("Notes", "English") .or_else() - .search("notes", "Italian") + .search("Notes", "Italian") .boost(10) )