diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.php.markdown
new file mode 100644
index 0000000000..a14556ce23
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.php.markdown
@@ -0,0 +1,64 @@
+# Include Query Explanations
+
+---
+
+{NOTE: }
+
+* When making a query, each document in the query results is assigned a **score**.
+ This score determines the order by which the documents come back in the results when requesting
+ to [order by score](../../../../client-api/session/querying/sort-query-results#order-by-score).
+
+* Each document in the results includes this score under the `@index-score` property in its metadata.
+
+* Use `includeExplanations` to get the score details and see how it was calculated.
+
+* In this page:
+ * [Include explanations in a query](../../../../client-api/session/querying/debugging/include-explanations#include-explanations-in-a-query)
+ * [View explanations](../../../../client-api/session/querying/debugging/include-explanations#view-explanations)
+ * [Syntax](../../../../client-api/session/querying/debugging/include-explanations#syntax)
+{NOTE/}
+
+---
+
+{PANEL: Include explanations in a query}
+
+{CODE-TABS}
+{CODE-TAB:php:query explain@ClientApi\Session\Querying\Debugging\IncludeExplanations.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where search(Name, "Syrup") or search(Name, "Lager")
+include explanations()
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE: }
+Please note that the First parameter is optional.
+If you intend to use the default options, just paste `null` instead of the options object.
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: View explanations}
+
+* The detailed explanations can be viewed from the **Query view** in Studio.
+
+* Running a query with `includeExplanations` will show an additional **Explanations Tab**.
+
+![Figure 1. Explanations in the Studio](images/include-explanations-1.png "Include explanations")
+
+* Sample score details:
+
+![Figure 2. View explanations](images/include-explanations-2.png "View explanation")
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\Debugging\IncludeExplanations.php /}
+
+| Parameters | Data type | Description |
+| - | - | - |
+| **$options** | `?ExplanationOptions` | This object is optional.
If you intend to use the default options, place `null` here. |
+| **&$explanations** | `Explanations` |
- A callback function (action) that takes `Explanations` as an argument. It will be called by the client with the resulting `Explanations`.
- You can interact with resulting Explanations inside your callback.
|
+
+{PANEL/}
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.python.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.python.markdown
index 9fe1c15ec7..2ed7c3f27d 100644
--- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.python.markdown
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/include-explanations.python.markdown
@@ -10,8 +10,7 @@
* Each document in the results includes this score under the `@index-score` property in its metadata.
-* **To get the score details** and see how it was calculated,
- you can use `include_explanations` when querying with a [document_query](../../../../client-api/session/querying/document-query/what-is-document-query).
+* Use `include_explanations` to get the score details** and see how it was calculated.
* In this page:
* [Include explanations in a query](../../../../client-api/session/querying/debugging/include-explanations#include-explanations-in-a-query)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.dotnet.markdown
index 64045e875a..04630f4920 100644
--- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.dotnet.markdown
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.dotnet.markdown
@@ -10,7 +10,7 @@
* By default, the timings stats are Not included in the query results, to avoid the measuring overhead.
-* __To include the query timings__ in the query results:
+* **To include the query timings** in the query results:
add a call to `Timings()` in your query code, or add `include timings()` to an RQL query.
See examples below.
@@ -41,9 +41,9 @@ include timings()
{PANEL: View timings}
-* The detailed timings can be viewed from the [Query view](../../../../studio/database/queries/query-view) in the Studio.
+* The detailed timings can be viewed from Studio's [Query view](../../../../studio/database/queries/query-view).
-* Running an RQL query with `include timings()` will show an additional __Timings Tab__
+* Running an RQL query with `include timings()` will show an additional **Timings Tab**
with a graphical representation of the time spent in each query part.
![Figure 1. Include timings graphical results](images/include-timings.png "Include timings results")
@@ -56,11 +56,11 @@ include timings()
| Parameter | Type | Description |
|-------------|----------------|-------------------------------------------------------------|
-| __timings__ | `QueryTimings` | An _out_ param that will be filled with the timings results |
+| ****timings** | `QueryTimings` | An _out_ param that will be filled with the timings results |
| `QueryTimings` | | |
|------------------|-------------------------------------|---------------------------------------------------|
-| __DurationInMs__ | `long` | Total duration |
-| __Timings__ | `IDictionary` | Dictionary with `QueryTimings` info per time part |
+| **DurationInMs** | `long` | Total duration |
+| **Timings** | `IDictionary` | Dictionary with `QueryTimings` info per time part |
{PANEL/}
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.js.markdown
index 98394d4a86..36c213a74d 100644
--- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.js.markdown
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.js.markdown
@@ -10,7 +10,7 @@
* By default, the timings stats are Not included in the query results, to avoid the measuring overhead.
-* __To include the query timings__ in the query results:
+* **To include the query timings** in the query results:
add a call to `timings()` in your query code, or add `include timings()` to an RQL query.
See examples below.
@@ -38,9 +38,9 @@ include timings()
{PANEL: View timings}
-* The detailed timings can be viewed from the [Query view](../../../../studio/database/queries/query-view) in the Studio.
+* The detailed timings can be viewed from Studio's [Query view](../../../../studio/database/queries/query-view).
-* Running an RQL query with `include timings()` will show an additional __Timings Tab__
+* Running an RQL query with `include timings()` will show an additional **Timings Tab**
with a graphical representation of the time spent in each query part.
![Figure 1. Include timings graphical results](images/include-timings.png "Include timings results")
@@ -53,11 +53,11 @@ include timings()
| Parameter | Type | Description |
|---------------------|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| __timingsCallback__ | `(timingsCallback) => void` | - A callback function with an output parameter.
- The parameter passed to the callback will be filled with the `QueryTimings` object when query returns.
|
+| **timingsCallback** | `(timingsCallback) => void` | - A callback function with an output parameter.
- The parameter passed to the callback will be filled with the `QueryTimings` object when query returns.
|
| `QueryTimings` | | |
|------------------|--------------------------------|---------------------------------------------------|
-| __durationInMs__ | `number` | Total duration |
-| __timings__ | `Record` | Dictionary with `QueryTimings` info per time part |
+| **durationInMs** | `number` | Total duration |
+| **timings** | `Record` | Dictionary with `QueryTimings` info per time part |
{PANEL/}
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.php.markdown
new file mode 100644
index 0000000000..08024f3ad5
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.php.markdown
@@ -0,0 +1,58 @@
+# Include Query Timings
+
+---
+
+{NOTE: }
+
+* When making a query,
+ you can request to get detailed stats of the time spent by RavenDB on each part of the query.
+ E.g. duration of search, loading documents, transforming results, total duration, etc.
+
+* By default, the timings stats are Not included in the query results, to avoid the measuring overhead.
+
+* **To include the query timings** in the query results:
+ add a call to the `timings()` method in your query code, or add `include timings()` to an RQL query.
+ See examples below.
+
+* In this page:
+ * [Include timings in a query](../../../../client-api/session/querying/debugging/query-timings#include-timings-in-a-query)
+ * [View timings](../../../../client-api/session/querying/debugging/query-timings#view-timings)
+ * [Syntax](../../../../client-api/session/querying/debugging/query-timings#syntax)
+
+{NOTE/}
+
+---
+
+{PANEL: Include timings in a query}
+
+{CODE-TABS}
+{CODE-TAB:php:query timing_2@ClientApi\Session\Querying\Debugging\IncludeQueryTimings.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where search(Name, "Syrup") or search(Name, "Lager")
+include timings()
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: View timings}
+
+* The detailed timings can be viewed from Studio's [Query view](../../../../studio/database/queries/query-view).
+
+* Running an RQL query with `include timings()` will show an additional **Timings Tab**
+ with a graphical representation of the time spent in each query part.
+
+![Figure 1. Include timings graphical results](images/include-timings.png "Include timings results")
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\Debugging\IncludeQueryTimings.php /}
+
+| Parameter | Type | Description |
+|-------------|----------------|---------------|
+| **&$timings** | `QueryTimings` | A callback function (action) that takes `QueryTimings` as an argument. It will be called by the client with the resulting `QueryTimings`. You can interact with the resulting `QueryTimings` inside your callback. |
+
+{PANEL/}
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.python.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.python.markdown
index deee58f446..342098abe7 100644
--- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.python.markdown
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.python.markdown
@@ -38,7 +38,7 @@ include timings()
{PANEL: View timings}
-* The detailed timings can be viewed from the [Query view](../../../../studio/database/queries/query-view) in the Studio.
+* The detailed timings can be viewed from Studio's [Query view](../../../../studio/database/queries/query-view).
* Running an RQL query with `include timings()` will show an additional **Timings Tab**
with a graphical representation of the time spent in each query part.
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/boost-search-results.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/boost-search-results.php.markdown
new file mode 100644
index 0000000000..16efa6f16d
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/boost-search-results.php.markdown
@@ -0,0 +1,78 @@
+# Boost Search Results
+
+---
+
+{NOTE: }
+
+* 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) indexing article.
+
+* The automatic ordering of the results by the score is configurable.
+ Learn more here: [automatic score-based ordering](../../../../indexes/boosting#automatic-score-based-ordering)
+
+* The calculated score details of the results can be retrieved if needed.
+ Learn more here: [get resulting score](../../../../client-api/session/querying/sort-query-results#get-resulting-score)
+
+* In this page:
+
+ * [Boost results - when making a full-text search](../../../../client-api/session/querying/text-search/boost-search-results#boost-results---when-making-a-full-text-search)
+ * [Boost results - when querying with where clause](../../../../client-api/session/querying/text-search/boost-search-results#boost-results---when-querying-with-where-clause)
+
+{NOTE/}
+
+---
+
+{PANEL: 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.
+
+{CODE-TABS}
+{CODE-TAB:php:query boost_1@ClientApi\Session\Querying\TextSearch\BoostResults.php /}
+{CODE-TAB:csharp:documentQuery boost_3@ClientApi\Session\Querying\TextSearch\BoostResults.cs /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees" where
+search(Notes, "English") or boost(search(Notes, "Italian"), 10)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: Boost results - when querying with where clause}
+
+`boost()` can be used to give different priorities to the results
+returned by different `where` clauses.
+
+{CODE-TABS}
+{CODE-TAB:php:query boost_4@ClientApi\Session\Querying\TextSearch\BoostResults.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Companies" where
+boost(startsWith(Name, "O"), 10) or
+boost(startsWith(Name, "P"), 50) or
+boost(endsWith(Name, "OP"), 90)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
+
+### Indexes
+
+- [Full-text search with index](../../../../indexes/querying/searching)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/ends-with-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/ends-with-query.php.markdown
new file mode 100644
index 0000000000..83ce5efbf2
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/ends-with-query.php.markdown
@@ -0,0 +1,74 @@
+# where_ends_with Query
+
+---
+
+{NOTE: }
+
+* You can query for documents having a field that ends with some specified string.
+
+* Unless explicitly specified, the string comparisons are case-insensitive by default.
+
+* **Note**:
+ This postfix search causes the server to perform a full index scan.
+ Instead, consider using a static index that indexes the field in reverse order
+ and then query with a [prefix search](../../../../client-api/session/querying/text-search/starts-with-query), which is much faster.
+
+* In this page:
+ * [where_ends_with](../../../../client-api/session/querying/text-search/ends-with-query#where_ends_with)
+ * [where_ends_with (case-sensitive)](../../../../client-api/session/querying/text-search/ends-with-query#where_ends_with-(case-sensitive))
+ * [Negate where_ends_with](../../../../client-api/session/querying/text-search/ends-with-query#negate-where_ends_with)
+
+{NOTE/}
+
+---
+
+{PANEL: where_ends_with}
+
+{CODE-TABS}
+{CODE-TAB:php:query endsWith_1@ClientApi\Session\Querying\TextSearch\EndsWith.php /}
+{CODE-TAB:csharp:documentQuery endsWith_3@ClientApi\Session\Querying\TextSearch\EndsWith.cs /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where endsWith(Name, "Lager")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: where_ends_with (case-sensitive)}
+
+{CODE-TABS}
+{CODE-TAB:php:query endsWith_4@ClientApi\Session\Querying\TextSearch\EndsWith.php /}
+{CODE-TAB:csharp:documentQuery endsWith_6@ClientApi\Session\Querying\TextSearch\EndsWith.cs /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where exact(endsWith(Name, "Lager"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: Negate where_ends_with}
+
+{CODE-TABS}
+{CODE-TAB:php:query endsWith_7@ClientApi\Session\Querying\TextSearch\EndsWith.php /}
+{CODE-TAB:csharp:documentQuery endsWith_9@ClientApi\Session\Querying\TextSearch\EndsWith.cs /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where (true and not endsWith(Name, "Lager"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [Starts-With query](../../../../client-api/session/querying/text-search/starts-with-query)
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
+
+### Indexes
+
+- [map indexes](../../../../indexes/map-indexes)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/exact-match-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/exact-match-query.php.markdown
new file mode 100644
index 0000000000..a86422ac58
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/exact-match-query.php.markdown
@@ -0,0 +1,92 @@
+# Exact Match Query
+
+---
+
+{NOTE: }
+
+* By default, when querying strings the string comparisons are **case-insensitive**.
+
+* To perform a **case-sensitive** search, use the `whereEquals` or `whereNotEquals`
+ method with its `exact` parameter set to `true`.
+
+* When making a dynamic query with an exact match, the auto-index created by the server indexes
+ the text of the document field using the [default exact analyzer](../../../../indexes/using-analyzers#ravendb)
+ where the casing of the original text is unchanged.
+
+* In this page:
+ * [Query with exact match](../../../../client-api/session/querying/text-search/exact-match-query#query-with-exact-match)
+ * [Query with exact match - nested object](../../../../client-api/session/querying/text-search/exact-match-query#query-with-exact-match---nested-object)
+ * [Syntax](../../../../client-api/session/querying/text-search/exact-match-query#syntax)
+
+{NOTE/}
+
+---
+
+{PANEL: Query with exact match}
+
+{NOTE: }
+
+{CODE-TABS}
+{CODE-TAB:php:query exact_1@ClientApi\Session\Querying\TextSearch\ExactMatch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where exact(FirstName == "Robert")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+* Executing the above query will generate the auto-index `Auto/Employees/ByExact(FirstName)`.
+
+* This auto-index will contain the following two index-fields:
+
+ * `FirstName`
+ Contains terms with the text from the indexed document field 'FirstName'.
+ Text is lower-cased and not tokenized.
+
+ * `exact(FirstName)`
+ Contain terms with the original text from the indexed document field 'FirstName'.
+ Casing is exactly the same as in the original text, and the text is not tokenized.
+ Making an exact query targets these terms to find matching documents.
+
+{PANEL/}
+
+{PANEL: Query with exact match - nested object}
+
+{NOTE: }
+
+{CODE-TABS}
+{CODE-TAB:php:query exact_4@ClientApi\Session\Querying\TextSearch\ExactMatch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Orders"
+where exact(Lines.ProductName == "Teatime Chocolate Biscuits")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\TextSearch\ExactMatch.php /}
+
+| Parameter | Type | Description |
+|---------------|----------------------------|-------------|
+| **$fieldName** | `string` | Search-field name |
+| **$value** | `string` | string to match with match condition |
+| **$exact** | `bool` | `false` - search is case-insensitive
`true` - search is case-sensitive |
+
+| Return Type | Description |
+| ------------- | ----- |
+| `DocumentQueryInterface` | Query results |
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
+- [How to Use Regex](../../../../client-api/session/querying/text-search/using-regex)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/full-text-search.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/full-text-search.php.markdown
new file mode 100644
index 0000000000..e701973532
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/full-text-search.php.markdown
@@ -0,0 +1,327 @@
+# Full-Text Search
+
+---
+
+{NOTE: }
+
+* This article is about running a full-text search with a **dynamic query**.
+ To learn how to run a full-text search using a static-index, see [full-text search with index](../../../../indexes/querying/searching).
+
+* Use the `search()` method to query for documents that contain specified term/s
+ within the text of the specified document field/s.
+
+* When running a full-text search with a dynamic query, the **auto-index** created by the server
+ breaks down the text of the searched document field using the [default search analyzer](../../../../indexes/using-analyzers#ravendb).
+ All generated terms are lower-cased, so the search is **case-insensitive**.
+
+* Gain additional control over term tokenization by running a full-text search
+ using a [static-index](../../../../indexes/querying/searching), where the used
+ analyzer is configurable.
+
+{INFO: }
+
+* A **boost** value can be set for each search to prioritize results.
+ Learn more in [boost search results](../../../../client-api/session/querying/text-search/boost-search-results).
+
+* User experience can be enhanced by requesting text fragments that **highlight**
+ the searched terms in the results. Learn more in [highlight search results](../../../../client-api/session/querying/text-search/highlight-query-results).
+{INFO/}
+
+---
+
+* In this page:
+ * [Search for single term](../../../../client-api/session/querying/text-search/full-text-search#search-for-single-term)
+ * [Search for multiple terms](../../../../client-api/session/querying/text-search/full-text-search#search-for-multiple-terms)
+ * [Search in multiple fields](../../../../client-api/session/querying/text-search/full-text-search#search-in-multiple-fields)
+ * [Search in complex object](../../../../client-api/session/querying/text-search/full-text-search#search-in-complex-object)
+ * [Search operators](../../../../client-api/session/querying/text-search/full-text-search#search-operators)
+ * [Search options](../../../../client-api/session/querying/text-search/full-text-search#search-options)
+ * [Using wildcards](../../../../client-api/session/querying/text-search/full-text-search#using-wildcards)
+ * [Syntax](../../../../client-api/session/querying/text-search/full-text-search#syntax)
+
+{NOTE/}
+
+---
+
+{PANEL: Search for single term}
+
+{NOTE: }
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_1@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_3@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "University")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+* Executing the above query will generate the auto-index `Auto/Employees/BySearch(Notes)`.
+
+* This auto-index will contain the following two index-fields:
+
+ * `Notes`
+ Contains terms with the original text from the indexed document field 'Notes'.
+ Text is lower-cased and Not tokenized.
+
+ * `search(Notes)`
+ Contains **lower-cased terms** that were tokenized from the 'Notes' field by the [default search analyzer](../../../../indexes/using-analyzers#ravendb) (RavenStandardAnalyzer).
+ Calling the `search()` method targets these terms to find matching documents.
+
+{PANEL/}
+
+{PANEL: Search for multiple terms}
+
+* You can search for multiple terms in the **same field** in a single search method.
+
+* By default, the logical operator between these terms is 'OR'.
+
+* This behavior can be modified. See section [Search operators](../../../../client-api/session/querying/text-search/full-text-search#search-operators).
+
+{NOTE: }
+
+**Pass terms in a string**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_4@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_6@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "University Sales Japanese")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{NOTE: }
+
+**Pass terms in a list**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_7@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "University Sales Japanese")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Search in multiple fields}
+
+* You can search for terms in **different fields** by making multiple search calls.
+
+* By default, the logical operator between consecutive search methods is 'OR'.
+
+* This behavior can be modified. See section [Search operators](../../../../client-api/session/querying/text-search/full-text-search#search-operators).
+
+{NOTE: }
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_9@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_11@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where (search(Notes, "French") or search(Title, "President"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Search in complex object}
+
+* You can search for terms within a complex object.
+
+* Any nested text field within the object is searchable.
+
+{NOTE: }
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_12@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_14@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Companies"
+where search(Address, "USA London")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Search operators}
+
+* By default, the logical operator between multiple terms within the **same field** in a search call is **OR**.
+
+* This can be modified using the `@operator` parameter as follows:
+
+{NOTE: }
+
+**AND**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_15@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_17@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "College German", and)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{NOTE: }
+
+**OR**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_18@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_20@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "College German")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Search options}
+
+Search options allow to:
+
+* Negate a search criteria.
+* Specify the logical operator used between **consecutive search calls**.
+
+{NOTE: }
+
+**Negate search**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_21@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_23@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Companies"
+where (exists(Address) and not search(Address, "USA"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{NOTE: }
+
+**Default behavior between search calls**:
+
+* By default, the logical operator between consecutive search methods is **OR**.
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_24@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_26@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Companies"
+where Contact.Title == "Owner" and
+(search(Address.Country, "France") or search(Name, "Markets"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{NOTE: }
+**AND search calls**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_27@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_29@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "French") and search(Title, "Manager")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{NOTE: }
+
+**Use options as bit flags**:
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_30@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_32@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "French") and
+(exists(Title) and not search(Title, "Manager"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Using wildcards}
+
+* Wildcards can be used to replace:
+ * Prefix of a searched term
+ * Postfix of a searched term
+ * Both prefix & postfix
+
+* Note:
+
+ * Searching with a wildcard as the prefix of the term (e.g. `*text`) is
+ not advised as it will cause the server to perform a full index scan.
+
+ * Instead, consider using a static-index that indexes the field in reverse order
+ and then query with a wildcard as the postfix, which is much faster.
+
+{NOTE: }
+
+{CODE-TABS}
+{CODE-TAB:php:query fts_33@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB:php:documentQuery fts_35@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees" where
+search(Notes, "art*") or
+search(Notes, "*logy") or
+search(Notes, "*mark*")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\TextSearch\FullTextSearch.php /}
+
+| Parameter | Type | Description |
+|-----------|------|-------------|
+| **$fieldName** | `string` | Name of the searched field. |
+| **$searchTerms** | `string` | A string containing the term or terms (separated by spaces) to search for. |
+| **$operator** | `?SearchOperator ` | Logical operator to use between multiple terms in the same Search method.
**Can be**: `SearchOperator::or` or `SearchOperator::and`
**Default**: `SearchOperator::or` |
+
+| Return Type | Description |
+| ------------| ----------- |
+| `DocumentQueryInterface` | Query results |
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [How to Use Regex](../../../../client-api/session/querying/text-search/using-regex)
+- [How to Query With Exact Match](../../../../client-api/session/querying/text-search/exact-match-query)
+
+### Indexes
+
+- [Analyzers](../../../../indexes/using-analyzers)
+- [Full-text search with index](../../../../indexes/querying/searching)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/fuzzy-search.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/fuzzy-search.php.markdown
new file mode 100644
index 0000000000..e38537c6fd
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/fuzzy-search.php.markdown
@@ -0,0 +1,50 @@
+# Fuzzy Search
+
+---
+
+{NOTE: }
+
+* A **fuzzy search** retrieves documents containing terms that closely match a given term
+ rather than exact matches, assisting in finding relevant results when the search term is
+ misspelled or has minor variations.
+
+* In this page:
+ * [Fuzzy search example](../../../../client-api/session/querying/text-search/fuzzy-search#fuzzy-search-example)
+ * [Syntax](../../../../client-api/session/querying/text-search/fuzzy-search#syntax)
+
+{NOTE/}
+
+---
+
+{PANEL: Fuzzy search example}
+
+{CODE-TABS}
+{CODE-TAB:php:query fuzzy_1@ClientApi\Session\Querying\TextSearch\FuzzySearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Companies"
+where fuzzy(Name = "Ernts Hnadel", 0.5)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\TextSearch\FuzzySearch.php /}
+
+| Parameter | Type | Description |
+|-------------|-----------|-------------|
+| **$fuzzy** | `float` | A value between `0.0` and `1.0`.
With a value closer to `1.0`, terms with a higher similarity are matched. |
+
+| Return Type | Description |
+| ----------- | ----------- |
+| `DocumentQueryInterface` | Query results |
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/highlight-query-results.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/highlight-query-results.php.markdown
new file mode 100644
index 0000000000..1867782027
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/highlight-query-results.php.markdown
@@ -0,0 +1,187 @@
+# Highlight Search Results
+---
+
+{NOTE: }
+
+* When making a [Full-Text Search query](../../../../client-api/session/querying/text-search/full-text-search),
+ in addition to retrieving documents that contain the searched terms in the results,
+ you can also request to get a **list of text fragments that highlight the searched terms**.
+
+* The highlighted terms can enhance user experience when searching for documents with specific content.
+
+* This article shows highlighting search results when making a **dynamic-query**.
+ For highlighting search results when querying a **static-index** see [highlight index search results](../../../../indexes/querying/highlighting).
+
+---
+
+* In this page:
+ * [Highlight - basic example](../../../../client-api/session/querying/text-search/highlight-query-results#highlight---basic-example)
+ * [Highlight tags](../../../../client-api/session/querying/text-search/highlight-query-results#highlight-tags)
+ * [Highlight results in Studio](../../../../client-api/session/querying/text-search/highlight-query-results#highlight-results-in-studio)
+ * [Highlight - customize tags](../../../../client-api/session/querying/text-search/highlight-query-results#highlight---customize-tags)
+ * [Highlight - projected results](../../../../client-api/session/querying/text-search/highlight-query-results#highlight---projected-results)
+ * [Syntax](../../../../client-api/session/querying/text-search/highlight-query-results#syntax)
+
+{NOTE/}
+
+---
+
+{PANEL: Highlight - basic example}
+
+{CODE-TABS}
+{CODE-TAB:php:query highlight_1@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where search(Notes, "sales")
+include highlight(Notes, 35, 4)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{CODE:php fragments_1@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+{NOTE: }
+
+#### Highlight tags
+
+* By default, the highlighted term is wrapped with the following html:
+ `term`
+
+* When requesting to highlight multiple terms,
+ the background color returned for each different term will be in the following order:
+
+ - yellow,
+ - lawngreen,
+ - aquamarine,
+ - magenta,
+ - palegreen,
+ - coral,
+ - wheat,
+ - khaki,
+ - lime,
+ - deepskyblue,
+ - deeppink,
+ - salmon,
+ - peachpuff,
+ - violet,
+ - mediumpurple,
+ - palegoldenrod,
+ - darkkhaki,
+ - springgreen,
+ - turquoise,
+ - powderblue
+
+* The html tags that wrap the highlighted terms can be **customized** to any other tags.
+ See [customize tags](../../../../client-api/session/querying/text-search/highlight-query-results#highlight---customize-tags) below.
+
+{NOTE/}
+
+{NOTE: }
+
+#### Highlight results in Studio
+
+![Figure 1. Fragments results](images/fragmentsResults.png "View highlighted fragments in the Query View")
+
+1. **Auto-Index**
+ This is the auto-index that was created by the server to serve the dynamic-query.
+
+2. **Results tab**
+ The results tab contains the resulting **documents** that match the provided RQL query.
+
+3. **Highlight tab**
+ The highlight tab shows the resulting **fragments** that were included in the query result.
+
+{NOTE/}
+
+{PANEL/}
+
+{PANEL: Highlight - customize tags}
+
+* The html tags that wrap the highlighted terms can be **customized** to any other tags.
+
+{CODE-TABS}
+{CODE-TAB:php:query highlight_4@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where (search(Notes, "sales") or search(Title, "manager"))
+include highlight(Notes, 35, 1, $p0), highlight(Title, 35, 1, $p1)
+{
+"p0":{"PreTags":["+++","<<<"],"PostTags":["+++",">>>"]},
+"p1":{"PreTags":["+++","<<<"],"PostTags":["+++",">>>"]}
+}
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{CODE:php fragments_2@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+{PANEL/}
+
+{PANEL: Highlight - projected results}
+
+* Highlighting can also be used when [projecting query results](../../../../client-api/session/querying/how-to-project-query-results).
+
+{CODE-TABS}
+{CODE-TAB:php:query highlight_6@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees" as x
+where search(x.Notes, "manager german")
+select { Name : "{0} {1}".format(x.FirstName, x.LastName), Title : x.Title }
+include highlight(Notes, 35, 2)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{CODE:php fragments_3@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax_1@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+| Parameter | Type | Description |
+|--------------------|-------------------------------|-------------------------------------|
+| **$fieldName** | `?string` | Name of the field that contains the searched terms to highlight |
+| **$fragmentLength** | `int` | Maximum length of a text fragment
Must be `>= 18` |
+| **$fragmentCount** | `int` | Maximum number of text fragments that will be returned |
+| **$options** | `?HighlightingOptions ` | Customizing options |
+| **&$highlightings** | `Highlightings` | A callback function to retrieve the highlighted text fragments for each returned result |
+
+
+
+**Highlighting options**:
+
+{CODE:php syntax_2@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+| Option | Type | Description |
+|--------------|-----------|--------------|
+| **$groupKey** | `?string` | Grouping key for the results.
Used when highlighting query results from a [Map-Reduce index](../../../../indexes/querying/highlighting#highlight-results---map-reduce-index).
If `None` results are grouped by document ID (default).
Note: Highlighting is Not available for dynamic aggregation queries. |
+| **$preTags** | `?StringArray` | Array of PRE tags used to wrap the highlighted search terms in the text fragments. |
+| **$postTags** | `?StringArray` | Array of POST tags used to wrap the highlighted search terms in the text fragments. |
+
+
+
+**Highlightings object**:
+
+{CODE:php syntax_3@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+| Property | Type | Description |
+|--------------------|------------|-------------|
+| **$fieldName** | `?string` | Name of the field that contains the searched terms to highlight |
+| **getResultIndents()** | function returning an `array` | The resulting keys (document IDs, or the map-reduce keys) |
+
+{CODE:php syntax_4@ClientApi\Session\Querying\TextSearch\HighlightQueryResults.php /}
+
+| Method | Return Type | Description |
+|-------------------|-------------|-------------|
+| **getFragments(?string $key)** | function returning an `array` | Returns the list of the highlighted text fragments for the passed document ID, or the map-reduce key |
+
+{PANEL/}
+
+## Related articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+
+### Indexes
+
+- [Highlight index search results](../../../../indexes/querying/highlighting)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/proximity-search.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/proximity-search.php.markdown
new file mode 100644
index 0000000000..7c3b4f2d75
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/proximity-search.php.markdown
@@ -0,0 +1,122 @@
+# Proximity Search
+
+---
+
+{NOTE: }
+
+* A **proximity search** retrieves documents containing search terms that are located within a specified distance from each other.
+ The distance is measured by the number of intermediate terms.
+
+* Use the `proximity` method when running a **full-text search** by the [search](../../../../client-api/session/querying/text-search/full-text-search) method.
+
+* In this page:
+ * [Why use proximity search](../../../../client-api/session/querying/text-search/proximity-search#why-use-proximity-search)
+ * [How proximity works](../../../../client-api/session/querying/text-search/proximity-search#how-proximity-works)
+ * [Proximity search examples](../../../../client-api/session/querying/text-search/proximity-search#proximity-search-examples)
+ * [Syntax](../../../../client-api/session/querying/text-search/proximity-search#syntax)
+
+{NOTE/}
+
+---
+
+{PANEL: Why use proximity search}
+
+* A basic linguistic assumption is that the proximity of words implies a relationship between them.
+
+* Proximity search helps match phrases while avoiding scattered or spread-out terms in the text.
+
+* By limiting the search to only include matches where the terms are within the specified maximum proximity,
+ the search results can be more relevant than those with scattered terms.
+
+{PANEL/}
+
+{PANEL: How proximity works}
+
+* When searching with some specified distance between search terms `term1` and `term2`:
+
+ * Retrieved documents will contain text in which `term1` and `term2` are separated by
+ the maximum number of terms specified or less.
+
+ * The search terms can be separated by fewer terms, but not more than the specified distance.
+
+ * Only the terms generated by the [search analyzer](../../../../indexes/using-analyzers#ravendb)
+ are considered towards the count of the maximum distance.
+ Words or tokens that are Not part of the generated terms are Not included in the proximity calculation.
+
+* Note:
+
+ * Search criteria should contain at least 2 search terms.
+
+ * Search terms must be simple string terms without wildcards.
+
+{PANEL/}
+
+{PANEL: Proximity search examples}
+
+## Proximity search (0 distance)
+
+{CODE-TABS}
+{CODE-TAB:php:Query proximity_1@ClientApi\Session\Querying\TextSearch\ProximitySearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where proximity(search(Notes, "fluent french"), 0)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+Running the above query on the Northwind sample data returns the following Employee documents:
+`employees/2-A`
+`employees/5-A`
+`employees/9-A`
+
+Each resulting document has the text 'fluent in French' in its 'Notes' field.
+
+The word "in" is not taken into account as it is Not part of the terms list generated
+by the analyzer. (Search is case-insensitive in this case.)
+
+{NOTE: }
+Documents containing text with the search terms appearing with no words between them
+(e.g. "fluent french") will also be returned.
+{NOTE/}
+
+## Proximity search (distance > 0)
+
+{CODE-TABS}
+{CODE-TAB:php:Query proximity_3@ClientApi\Session\Querying\TextSearch\ProximitySearch.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Employees"
+where proximity(search(Notes, "fluent french"), 5)
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+Running the above query on the Northwind sample data returns the following Employee documents:
+`employees/2-A`
+`employees/5-A`
+`employees/6-A`
+`employees/9-A`
+
+This time document 'employees/6-A' was added to the previous results since it contains the phrase:
+"fluent in Japanese and can read and write French"
+where the search terms are separated by a count of 4 terms.
+
+"in" & "and" are not taken into account as they are not part of the terms list generated
+by the analyzer.(Search is case-insensitive in this case).
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\TextSearch\ProximitySearch.php /}
+
+| Parameter | Type | Description |
+|---------------|-------|-------------------------------------------------------------------------------|
+| **$proximity** | `int` | The maximum number of terms between the search terms.
Can be `0` or more. |
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [What is a DocumentQuery](../../../../client-api/session/querying/document-query/what-is-document-query)
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/starts-with-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/starts-with-query.php.markdown
new file mode 100644
index 0000000000..eecb706ec1
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/starts-with-query.php.markdown
@@ -0,0 +1,76 @@
+# Starts-With Query
+
+---
+
+{NOTE: }
+
+* You can query for documents having a field that starts with some specified string.
+
+* Unless explicitly specified, the string comparisons are case-insensitive by default.
+
+* In this page:
+ * [StartsWith](../../../../client-api/session/querying/text-search/starts-with-query#startswith)
+ * [StartsWith (case-sensitive)](../../../../client-api/session/querying/text-search/starts-with-query#startswith-(case-sensitive))
+ * [Negate StartsWith](../../../../client-api/session/querying/text-search/starts-with-query#negate-startswith)
+
+{NOTE/}
+
+---
+
+{PANEL: StartsWith}
+
+The results will contain only Product documents having a 'Name' field
+that starts with any case variation of 'ch'.
+
+{CODE-TABS}
+{CODE-TAB:php:query startsWith_1@ClientApi\Session\Querying\TextSearch\StartsWith.php /}
+{CODE-TAB:php:documentQuery startsWith_3@ClientApi\Session\Querying\TextSearch\StartsWith.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where startsWith(Name, "Ch")
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: StartsWith (case-sensitive)}
+
+The results will contain only Product documents having a 'Name' field
+that starts with 'Ch'.
+
+{CODE-TABS}
+{CODE-TAB:php:query startsWith_4@ClientApi\Session\Querying\TextSearch\StartsWith.php /}
+{CODE-TAB:php:documentQuery startsWith_6@ClientApi\Session\Querying\TextSearch\StartsWith.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where exact(startsWith(Name, "Ch"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: Negate StartsWith}
+
+The results will contain only Product documents having a 'Name' field
+that does NOT start with 'ch' or any other case variations of it.
+
+{CODE-TABS}
+{CODE-TAB:php:query startsWith_7@ClientApi\Session\Querying\TextSearch\StartsWith.php /}
+{CODE-TAB:php:documentQuery startsWith_9@ClientApi\Session\Querying\TextSearch\StartsWith.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where (true and not startsWith(Name, "Ch"))
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [Ends-With query](../../../../client-api/session/querying/text-search/ends-with-query)
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
+
+
diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/using-regex.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/using-regex.php.markdown
new file mode 100644
index 0000000000..1cd13eb4b9
--- /dev/null
+++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/text-search/using-regex.php.markdown
@@ -0,0 +1,35 @@
+# Using Regex
+
+To return only documents that match a regular expression ("regex"),
+use the `whereRegex` method which enables RavenDB to perform server-side pattern matching queries.
+
+The supplied regular expression must be [.NET compatible](https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=netframework-4.7.1).
+
+## Example
+
+Load all products whose name starts with 'N' or 'A'.
+
+{CODE-TABS}
+{CODE-TAB:php regex_1@ClientApi\Session\Querying\TextSearch\UsingRegex.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from Products
+where regex(Name, '^[NA]')
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+## Syntax
+
+{CODE:php syntax@ClientApi\Session\Querying\TextSearch\UsingRegex.php /}
+
+| Parameter | Type | Description |
+|---------------|-------|-------------------------------------------------------------------------------|
+| **$fieldName** | `?string` | Name of the field to query |
+| **$pattern** | `?string` | Pattern to query for |
+
+## Related Articles
+
+### Session
+
+- [Query overview](../../../../client-api/session/querying/how-to-query)
+- [Full-text search](../../../../client-api/session/querying/text-search/full-text-search)
+- [Query with exact match](../../../../client-api/session/querying/text-search/exact-match-query)
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/Debugging/IncludeExplanations.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/Debugging/IncludeExplanations.php
new file mode 100644
index 0000000000..68500fe003
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/Debugging/IncludeExplanations.php
@@ -0,0 +1,41 @@
+openSession();
+ try {
+ # region explain
+ $explanations = new Explanations();
+
+ /** @var array $syrups */
+ $syrups = $session->advanced()->documentQuery(Product::class)
+ ->includeExplanations(null, $explanations)
+ ->search("Name", "Syrup")
+ ->toList();
+
+ $scoreDetails = $explanations->getExplanations($syrups[0]->getId());
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/Debugging/IncludeQueryTimings.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/Debugging/IncludeQueryTimings.php
new file mode 100644
index 0000000000..ff7d0a0d23
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/Debugging/IncludeQueryTimings.php
@@ -0,0 +1,42 @@
+openSession();
+ try {
+ # region timing_2
+ $timings = new QueryTimings();
+
+ /** @var array $resultsWithTimings */
+ $resultsWithTimings = $session->advanced()->documentQuery(Product::class)
+ ->timings($timings)
+ ->search("Name", "Syrup")
+ ->toList();
+
+ /** @var array $timingsMap */
+ $timingsMap = $timings->getTimings();
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/BoostResults.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/BoostResults.php
new file mode 100644
index 0000000000..a4404a7a74
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/BoostResults.php
@@ -0,0 +1,100 @@
+openSession();
+ try {
+ # region boost_1
+ /** @var array $employees */
+ $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.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region boost_3
+ /** @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).
+ //
+ // * 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.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region boost_4
+ /** @var array $companies */
+ $companies = $session->advanced()
+ // Make a dynamic DocumentQuery on 'Companies' collection
+ ->documentQuery(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.
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/EndsWith.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/EndsWith.php
new file mode 100644
index 0000000000..cd998870ef
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/EndsWith.php
@@ -0,0 +1,126 @@
+openSession();
+ try {
+ # region endsWith_1
+ /** @var array $products */
+ $products = $session
+ ->query(Product::class)
+ // Call 'whereEndsWith' on the field
+ // Pass the postfix to search by
+ ->whereEndsWith("Name", "Lager")
+ ->toList();
+
+ // Results will contain only Product documents having a 'Name' field
+ // that ends with any case variation of 'lager'
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region endsWith_3
+ /** @var array $products */
+ $products = $session->advanced()
+ ->documentQuery(Product::class)
+ // Call 'whereEndsWith'
+ // Pass the document field and the postfix to search by
+ ->whereEndsWith("Name", "Lager")
+ ->toList();
+
+ // Results will contain only Product documents having a 'Name' field
+ // that ends with any case variation of 'lager'
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region endsWith_4
+ /** @var array $products */
+ $products = $session
+ ->query(Product::class)
+ // Pass 'exact: true' to search for an EXACT postfix match
+ ->whereEndsWith("Name", "Lager", true)
+ ->toList();
+
+ // Results will contain only Product documents having a 'Name' field
+ // that ends with 'Lager'
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region endsWith_6
+ /** @var array $products */
+ $products = $session->advanced()
+ ->documentQuery(Product::class)
+ // Call 'whereEndsWith'
+ // Pass 'exact: true' to search for an EXACT postfix match
+ ->whereEndsWith("Name", "Lager", true)
+ ->toList();
+
+ // Results will contain only Product documents having a 'Name' field
+ // that ends with 'Lager'
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region endsWith_7
+ /** @var array $products */
+ $products = $session
+ ->query(Product::class)
+ // Call 'Not' to negate the next predicate
+ ->not()
+ // Call 'whereEndsWith' on the field
+ // Pass the postfix to search by
+ ->whereEndsWith("Name", "Lager")
+ ->toList();
+
+ // Results will contain only Product documents having a 'Name' field
+ // that does NOT end with 'lager' or any other case variations of it
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region endsWith_9
+ /** @var array $products */
+ $products = $session->advanced()
+ ->documentQuery(Product::class)
+ // Call 'Not' to negate the next predicate
+ ->not()
+ // Call 'whereEndsWith'
+ // Pass the document field and the postfix to search by
+ ->whereEndsWith("Name", "Lager")
+ ->toList();
+
+ // Results will contain only Product documents having a 'Name' field
+ // that does NOT end with 'lager' or any other case variations of it
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/ExactMatch.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/ExactMatch.php
new file mode 100644
index 0000000000..7889f37176
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/ExactMatch.php
@@ -0,0 +1,63 @@
+openSession();
+ try {
+ # region exact_1
+ // load all entities from 'Employees' collection
+ // where FirstName field's contents equals 'Robert' (case sensitive match)
+
+ /** @var array $employees */
+ $employees = $session->query(Employee::class)
+ ->whereEquals("FirstName", "Robert", true)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region exact_4
+ // return all entities from the 'Orders' collection which contain
+ // at least one order line with 'Teatime Chocolate Biscuits' product
+ // perform a case-sensitive match
+ /** @var array $orders */
+ $orders = $session->query(Order::class)
+ ->whereEquals("Lines[].ProductName", "Teatime Chocolate Biscuits", true)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
+
+class Employee
+{
+}
+
+class Order
+{
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/FullTextSearch.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/FullTextSearch.php
new file mode 100644
index 0000000000..d5da588e9c
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/FullTextSearch.php
@@ -0,0 +1,529 @@
+openSession();
+ try {
+ # region fts_1
+ /** @var array $employees */
+ $employees = $session
+ // Make a dynamic query on Employees collection
+ ->query(Employee::class)
+ // * Call 'Search' to make a Full-Text search
+ // * Search is case-insensitive
+ // * Look for documents containing the term 'University' within their 'Notes' field
+ ->search("Notes", "University")
+ ->toList();
+
+ // Results will contain Employee documents that have
+ // any case variation of the term 'university' in their 'Notes' field.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_3
+ /** @var array $employees */
+ $employees = $session->advanced()
+ // Make a dynamic DocumentQuery on Employees collection
+ ->documentQuery(Employee::class)
+ // * Call 'Search' to make a Full-Text search
+ // * Search is case-insensitive
+ // * Look for documents containing the term 'University' within their 'Notes' field
+ ->search("Notes", "University")
+ ->toList();
+
+ // Results will contain Employee documents that have
+ // any case variation of the term 'university' in their 'Notes' field.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search for multiple terms - string
+ // ==================================
+ $session = $store->openSession();
+ try {
+ # region fts_4
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ // * Pass multiple terms in a single string, separated by spaces.
+ // * Look for documents containing either 'University' OR 'Sales' OR 'Japanese'
+ // within their 'Notes' field
+ ->search("Notes", "University Sales Japanese")
+ ->toList();
+
+ // * Results will contain Employee documents that have at least one of the specified terms.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_6
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // * Pass multiple terms in a single string, separated by spaces.
+ // * Look for documents containing either 'University' OR 'Sales' OR 'Japanese'
+ // within their 'Notes' field
+ ->search("Notes", "University Sales Japanese")
+ ->toList();
+
+ // * Results will contain Employee documents that have at least one of the specified terms.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search for multiple terms - list
+ // ==================================
+ $session = $store->openSession();
+ try {
+ # region fts_7
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ // * Pass terms in array.
+ // * Look for documents containing either 'University' OR 'Sales' OR 'Japanese'
+ // within their 'Notes' field
+ ->search("Notes", ["University", "Sales", "Japanese"])
+ ->toList();
+
+ // * Results will contain Employee documents that have at least one of the specified terms.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search in multiple fields
+ // =========================
+ $session = $store->openSession();
+ try {
+ # region fts_9
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ // * Look for documents containing:
+ // 'French' in their 'Notes' field OR 'President' in their 'Title' field
+ ->search("Notes", "French")
+ ->search("Title", "President")
+ ->toList();
+
+ // * Results will contain Employee documents that have
+ // at least one of the specified fields with the specified terms.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_11
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // * Look for documents containing:
+ // 'French' in their 'Notes' field OR 'President' in their 'Title' field
+ ->search("Notes", "French")
+ ->search("Title", "President")
+ ->toList();
+
+ // * Results will contain Employee documents that have
+ // at least one of the specified fields with the specified terms.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search in complex object
+ // ========================
+ $session = $store->openSession();
+ try {
+ # region fts_12
+ /** @var array $companies */
+ $companies = $session
+ ->query(Company::class)
+ // * Look for documents that contain:
+ // the term 'USA' OR 'London' in any field within the complex 'Address' object
+ ->search("Address", "USA London")
+ ->toList();
+
+ // * Results will contain Company documents that are located either in 'USA' OR in 'London'.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_14
+ /** @var array $companies */
+ $companies = $session->advanced()
+ ->documentQuery(Company::class)
+ // * Look for documents that contain:
+ // the term 'USA' OR 'London' in any field within the complex 'Address' object
+ ->search("Address", "USA London")
+ ->toList();
+
+ // * Results will contain Company documents that are located either in 'USA' OR in 'London'.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search operators - AND
+ // ======================
+ $session = $store->openSession();
+ try {
+ # region fts_15
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ // * Pass operator with SearchOperator::and()
+ ->search("Notes", "College German", SearchOperator::and())
+ ->toList();
+
+ // * Results will contain Employee documents that have BOTH 'College' AND 'German'
+ // in their 'Notes' field.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_17
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // * Pass operator with SearchOperator::and()
+ ->search("Notes", "College German", SearchOperator::and())
+ ->toList();
+
+ // * Results will contain Employee documents that have BOTH 'College' AND 'German'
+ // in their 'Notes' field.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search operators - OR
+ // =====================
+ $session = $store->openSession();
+ try {
+ # region fts_18
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ // * Pass operator with SearchOperator::or()
+ ->search("Notes", "College German", SearchOperator::or())
+ ->toList();
+
+ // * Results will contain Employee documents that have EITHER 'College' OR 'German'
+ // in their 'Notes' field.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_20
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // * Pass operator with SearchOperator::or()
+ ->search("Notes", "College German", SearchOperator::or())
+ ->toList();
+
+ // * Results will contain Employee documents that have EITHER 'College' OR 'German'
+ // in their 'Notes' field.
+ // * Search is case-insensitive.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search options - Not
+ // ====================
+ $session = $store->openSession();
+ try {
+ # region fts_21
+ /** @var array $companies */
+ $companies = $session
+ ->query(Company::class)
+ # Call 'not()' to negate the next search call
+ ->not()
+ ->search("Address", "USA")
+ ->toList();
+
+ // * Results will contain Company documents are NOT located in 'USA'
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_23
+ /** @var array $companies */
+ $companies = $session->advanced()
+ ->documentQuery(Company::class)
+ ->openSubclause()
+ // Call 'not()' to negate the next search call
+ ->not()
+ ->search("Address", "USA")
+ ->closeSubclause()
+ ->toList();
+
+ // * Results will contain Company documents are NOT located in 'USA'
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search options - Default
+ // ========================
+ $session = $store->openSession();
+ try {
+ # region fts_24
+ /** @var array $companies */
+ $companies = $session
+ ->query(Company::class)
+ ->whereEquals("Contact.Title", "Owner")
+ // Operator AND will be used with previous 'Where' predicate
+ ->search("Address.Country", "France")
+ // Operator OR will be used between the two 'Search' calls by default
+ ->search("Name", "Markets")
+ ->toList();
+
+ // * Results will contain Company documents that have:
+ // ('Owner' as the 'Contact.Title')
+ // AND
+ // (are located in 'France' OR have 'Markets' in their 'Name' field)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_26
+ /** @var array $companies */
+ $companies = $session->advanced()
+ ->documentQuery(Company::class)
+ ->whereEquals("Contact.Title", "Owner")
+ // Operator AND will be used with previous 'Where' predicate
+ // Call 'openSubclause()' to open predicate block
+ ->openSubclause()
+ ->search("Address.Country", "France")
+ // Operator OR will be used between the two 'Search' calls by default
+ ->search("Name", "Markets")
+ // Call 'closeSubclause()' to close predicate block
+ ->closeSubclause()
+ ->toList();
+
+ // * Results will contain Company documents that have:
+ // ('Owner' as the 'Contact.Title')
+ // AND
+ // (are located in 'France' OR have 'Markets' in their 'Name' field)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search options - AND
+ // ====================
+ $session = $store->openSession();
+ try {
+ # region fts_27
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ ->search("Notes", "French")
+ // Call 'AndAlso' so that operator AND will be used with previous 'search' call
+ ->andAlso()
+ ->search("Title", "Manager")
+ ->toList();
+
+ // * Results will contain Employee documents that have:
+ // ('French' in their 'Notes' field)
+ // AND
+ // ('Manager' in their 'Title' field)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_29
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ ->search("Notes", "French")
+ // Call 'andAlso()' so that operator AND will be used with previous 'search' call
+ ->andAlso()
+ ->search("Title", "Manger")
+ ->toList();
+
+ // * Results will contain Employee documents that have:
+ // ('French' in their 'Notes' field)
+ // AND
+ // ('Manager' in their 'Title' field)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Search options - Flags
+ // ======================
+ $session = $store->openSession();
+ try {
+ # region fts_30
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ ->search("Notes", "French")
+ // Call 'andAlso()' so that operator AND will be used with previous 'search' call
+ ->andAlso()
+ ->openSubclause()
+ // Call 'not()' to negate the next search call
+ ->not()
+ ->search("Title", "Manager")
+ ->closeSubclause()
+ ->toList();
+
+ // * Results will contain Employee documents that have:
+ // ('French' in their 'Notes' field)
+ // AND
+ // (do NOT have 'Manager' in their 'Title' field)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_32
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ ->search("Notes", "French")
+ // Call 'andAlso()' so that operator AND will be used with previous 'search' call
+ ->andAlso()
+ ->openSubclause()
+ // Call 'not()' to negate the next search call
+ ->not()
+ ->search("Title", "Manager")
+ ->closeSubclause()
+ ->toList();
+
+ // * Results will contain Employee documents that have:
+ // ('French' in their 'Notes' field)
+ // AND
+ // (do NOT have 'Manager' in their 'Title' field)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ // Using wildcards
+ // ===============
+ $session = $store->openSession();
+ try {
+ # region fts_33
+ /** @var array $employees */
+ $employees = $session
+ ->query(Employee::class)
+ // Use '*' to replace one or more characters
+ ->search("Notes", "art*")
+ ->search("Notes", "*logy")
+ ->search("Notes", "*mark*")
+ ->ToList();
+
+ // Results will contain Employee documents that have in their 'Notes' field:
+ // (terms that start with 'art') OR
+ // (terms that end with 'logy') OR
+ // (terms that have the text 'mark' in the middle)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region fts_35
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // Use '*' to replace one ore more characters
+ ->search("Notes", "art*")
+ ->search("Notes", "*logy")
+ ->search("Notes", "*mark*")
+ ->toList();
+
+ // Results will contain Employee documents that have in their 'Notes' field:
+ // (terms that start with 'art') OR
+ // (terms that end with 'logy') OR
+ // (terms that have the text 'mark' in the middle)
+ //
+ // * Search is case-insensitive
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/FuzzySearch.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/FuzzySearch.php
new file mode 100644
index 0000000000..be912e2f6c
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/FuzzySearch.php
@@ -0,0 +1,44 @@
+openSession();
+ try {
+ # region fuzzy_1
+ /** @var array $companies */
+ $companies = $session->advanced()
+ ->documentQuery(Company::class)
+ // Query with a term that is misspelled
+ ->whereEquals("Name", "Ernts Hnadel")
+ // Call 'Fuzzy'
+ // Pass the required similarity, a decimal param between 0.0 and 1.0
+ ->fuzzy(0.5)
+ ->toList();
+
+ // Running the above query on the Northwind sample data returns document: companies/20-A
+ // which contains "Ernst Handel" in its Name field.
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/HighlightQueryResults.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/HighlightQueryResults.php
new file mode 100644
index 0000000000..728a09b7f3
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/HighlightQueryResults.php
@@ -0,0 +1,287 @@
+map = "docs.Select(doc => new { " .
+ " text = doc.text" .
+ "})";
+
+ $this->index("text", FieldIndexing::search());
+ $this->store("text", FieldStorage::yes());
+ $this->termVector("text", FieldTermVector::withPositionsAndOffsets());
+ }
+}
+
+class SearchItem
+{
+ private ?string $id = null;
+ private ?string $text = null;
+
+ public function getId(): ?string
+ {
+ return $this->id;
+ }
+
+ public function setId(?string $id): void
+ {
+ $this->id = $id;
+ }
+
+ public function getText(): ?string
+ {
+ return $this->text;
+ }
+
+ public function setText(?string $text): void
+ {
+ $this->text = $text;
+ }
+}
+
+class EmployeeDetails
+{
+ private ?string $name = null;
+ private ?string $title = null;
+
+ public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+ public function setName(?string $name): void
+ {
+ $this->name = $name;
+ }
+
+ public function getTitle(): ?string
+ {
+ return $this->title;
+ }
+
+ public function setTitle(?string $title): void
+ {
+ $this->title = $title;
+ }
+}
+
+interface FooInterface
+{
+ # region syntax_1
+ function highlight(
+ ?string $fieldName,
+ int $fragmentLength,
+ int $fragmentCount,
+ ?HighlightingOptions $options,
+ Highlightings &$highlightings
+ ): DocumentQueryInterface;
+ # endregion
+}
+
+class Foo
+{
+ # region syntax_2
+ private ?string $groupKey;
+ private ?StringArray $preTags = null;
+ private ?StringArray $postTags = null;
+
+ // getters and setters
+ # endregion
+}
+
+
+class HighlightingsClass
+{
+ # region syntax_3
+ private ?string $fieldName = null;
+ public function getResultIndents(): array;
+ # endregion
+}
+
+interface FooInterface2
+{
+ # region syntax_4
+ public function getFragments(?string $key): array;
+ # endregion
+}
+
+class HighlightQueryResults
+{
+ public function examples(): void
+ {
+ $store = DocumentStoreHolder::getStore();
+ try {
+ $session = $store->openSession();
+ try {
+ # region highlight_1
+ // Make a full-text search dynamic query:
+ // ======================================
+
+ $highlightings = new Highlightings();
+
+ /** @var array $employeesResults */
+ $employeesResults = $session
+ // Make a dynamic query on 'Employees' collection
+ ->query(Employee::class)
+ // Search for documents containing the term 'sales' in their 'Notes' field
+ ->search("Notes", "sales")
+ // Request to highlight the searched term by calling 'highlight()'
+ ->highlight(
+ "Notes", // The document-field name in which we search
+ 35, // Max length of each text fragment
+ 4, // Max number of fragments to return per document
+ null, // Put null to use default options
+ $highlightings) // An out param for getting the highlighted text fragments
+
+ // Execute the query
+ ->toList();
+ # endregion
+
+ # region fragments_1
+ // Process results:
+ // ================
+
+ // 'employeesResults' contains all Employee DOCUMENTS that have 'sales' in their 'Notes' field.
+ // 'salesHighlights' contains the text FRAGMENTS that highlight the 'sales' term.
+
+ $builder = '';
+
+ /** @var SearchItem $employee */
+ foreach ($employeesResults as $employee) {
+ // Call 'GetFragments' to get all fragments for the specified employee Id
+ $fragments = $highlightings->getFragments($employee->getId());
+ foreach ($fragments as $fragment) {
+ $builder .= '- Doc: ' . $employee->getId() . ' Fragment: ' . $fragment . '
';
+ }
+ }
+
+ $builder .= '
';
+ $fragmentsHtml = $builder;
+
+ // The resulting fragmentsHtml:
+ // ============================
+
+ //
+ // - Doc: employees/2-A Fragment: company as a sales
+ // - Doc: employees/2-A Fragment: promoted to sales manager in
+ // - Doc: employees/2-A Fragment: president of sales in March 1993
+ // - Doc: employees/2-A Fragment: member of the Sales Management
+ // - Doc: employees/3-A Fragment: hired as a sales associate in
+ // - Doc: employees/3-A Fragment: promoted to sales representativ
+ // - Doc: employees/5-A Fragment: company as a sales representativ
+ // - Doc: employees/5-A Fragment: promoted to sales manager in
+ // - Doc: employees/5-A Fragment: Sales Management."
+ // - Doc: employees/6-A Fragment: for the Sales Professional.
+ //
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region highlight_4
+ // Define customized tags to use for highlighting the searched terms
+ // =================================================================
+
+ $salesHighlights = new Highlightings();
+ $managerHighlights = new Highlightings();
+
+ $tagsToUse = new HighlightingOptions();
+ // Provide strings of your choice to 'PreTags' & 'PostTags', e.g.:
+ // the first term searched for will be wrapped with '+++'
+ // the second term searched for will be wrapped with '<<<' & '>>>'
+ $tagsToUse->setPreTags(["+++", "<<<"]);
+ $tagsToUse->setPostTags(["+++", ">>>"]);
+
+ // Make a full-text search dynamic query:
+ // ======================================
+ $employeesResults = $session
+ ->query(Employee::class)
+ // Search for:
+ // * documents containing the term 'sales' in their 'Notes' field
+ // * OR for documents containing the term 'manager' in their 'Title' field
+ ->search("Notes", "sales")
+ ->search("Title", "manager")
+ // Call 'Highlight' for each field searched
+ // Pass 'tagsToUse' to OVERRIDE the default tags used
+ ->highlight("Notes", 35, 1, $tagsToUse, $salesHighlights)
+ ->highlight("Title", 35, 1, $tagsToUse, $managerHighlights)
+ ->toList();
+ # endregion
+
+ # region fragments_2
+ // The resulting salesHighlights fragments:
+ // ========================================
+
+ // "for the +++Sales+++ Professional."
+ // "hired as a +++sales+++ associate in"
+ // "company as a +++sales+++"
+ // "company as a +++sales+++ representativ"
+
+ // The resulting managerHighlights fragments:
+ // ==========================================
+
+ // "Sales <<>>"
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region highlight_6
+ // Make a full-text search dynamic query & project results:
+ // ========================================================
+ $termsHighlights = new Highlightings();
+
+ /** @var array $employeesProjectedResults */
+ $employeesProjectedResults = $session
+ ->query(Employee::class)
+ // Search for documents containing 'sales' or 'german' in their 'Notes' field
+ ->search("Notes", "manager german")
+ // Request to highlight the searched terms from the 'Notes' field
+ ->highlight("Notes", 35, 2, null, $termsHighlights)
+ // Define the projection
+ ->selectFields(EmployeeDetails::class, QueryData::customFunction("o", "{ name: o.FirstName + ' ' + o.LastName, title: o.Title }"))
+ ->toList();
+ # endregion
+
+ # region fragments_3
+ // The resulting fragments from termsHighlights:
+ // =============================================
+
+ // "to sales manager in March"
+ // "and reads German. He joined"
+ // "to sales manager in January"
+ // "in French and German."
+
+ // NOTE: each search term is wrapped with a different color
+ // 'manager' is wrapped with yellow
+ // 'german' is wrapped with lawngreen
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ } finally {
+ $store->close();
+ }
+ }
+}
+
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/ProximitySearch.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/ProximitySearch.php
new file mode 100644
index 0000000000..2f149d5c35
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/ProximitySearch.php
@@ -0,0 +1,83 @@
+openSession();
+ try {
+ # region proximity_2
+ $session->advanced()
+ ->documentQuery(Fox::class)
+ ->search("name", "quick fox")
+ ->proximity(2)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region proximity_1
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // Make a full-text search with search terms
+ ->search("Notes", "fluent french")
+ // Call 'Proximity' with 0 distance
+ ->proximity(0)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region proximity_3
+ /** @var array $employees */
+ $employees = $session->advanced()
+ ->documentQuery(Employee::class)
+ // Make a full-text search with search terms
+ ->search("Notes", "fluent french")
+ // Call 'Proximity' with distance 5
+ ->proximity(4)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ } finally {
+ $store->close();
+ }
+ }
+}
+
+class Fox
+{
+ private ?string $name = null;
+
+ public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+ public function setName(?string $name): void
+ {
+ $this->name = $name;
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/StartsWith.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/StartsWith.php
new file mode 100644
index 0000000000..6d3ac2b467
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/StartsWith.php
@@ -0,0 +1,108 @@
+openSession();
+ try {
+ # region startsWith_1
+ /** @var array $products */
+ $products = $session
+ ->query(Product::class)
+ // Call 'StartsWith' on the field
+ // Pass the prefix to search by
+ ->whereStartsWith("Name", "Ch")
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region startsWith_3
+ /** @var array $products */
+ $products = $session->advanced()
+ ->documentQuery(Product::class)
+ // Call 'WhereStartsWith'
+ // Pass the document field and the prefix to search by
+ ->whereStartsWith("Name", "Ch")
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region startsWith_4
+ /** @var array $products */
+ $products = $session->advanced()
+ ->query(Product::class)
+ // Pass 'exact: true' to search for an EXACT prefix match
+ ->whereStartsWith("Name", "Ch", true)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region startsWith_6
+ /** @var array $products */
+ $products = $session->advanced()
+ ->documentQuery(Product::class)
+ // Call 'WhereStartsWith'
+ // Pass 'exact: true' to search for an EXACT prefix match
+ ->whereStartsWith("Name", "Ch", true)
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region startsWith_7
+ /** @var array $products */
+ $products = $session
+ ->query(Product::class)
+ # Negate next statement
+ ->not()
+ // Call 'StartsWith' on the field
+ // Pass the prefix to search by
+ ->whereStartsWith("Name", "Ch")
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ $session = $store->openSession();
+ try {
+ # region startsWith_9
+ /** @var array $products */
+ $products = $session->advanced()
+ ->documentQuery(Product::class)
+ // Call 'Not' to negate the next predicate
+ ->not()
+ // Call 'WhereStartsWith'
+ // Pass the document field and the prefix to search by
+ ->whereStartsWith("Name", "Ch")
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}
diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/UsingRegex.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/UsingRegex.php
new file mode 100644
index 0000000000..ac061c4b33
--- /dev/null
+++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/TextSearch/UsingRegex.php
@@ -0,0 +1,52 @@
+openSession();
+ try {
+ # region regex_1
+ /** @var array $products */
+ $products = $session
+ ->query(Product::class)
+ ->whereRegex("Name", "^[NA]")
+ ->toList();
+ # endregion
+ } finally {
+ $session->close();
+ }
+
+ } finally {
+ $store->close();
+ }
+ }
+}
+
+class User
+{
+ public ?string $firstName = null;
+
+ public function getFirstName(): ?string
+ {
+ return $this->firstName;
+ }
+
+ public function setFirstName(?string $firstName): void
+ {
+ $this->firstName = $firstName;
+ }
+}
diff --git a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.php.markdown b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.php.markdown
new file mode 100644
index 0000000000..8a17eb73e8
--- /dev/null
+++ b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/debugging/query-timings.php.markdown
@@ -0,0 +1,67 @@
+# Include Query Timings
+
+---
+
+{NOTE: }
+
+* When making a query,
+ you can request to get detailed stats of the time spent by RavenDB on each part of the query.
+ E.g. duration of search, loading documents, transforming results, total duration, etc.
+
+* By default, the timings stats are Not included in the query results, to avoid the measuring overhead.
+
+* **To include the query timings** in the query results:
+ add a call to the `timings()` method in your query code, or add `include timings()` to an RQL query.
+ See examples below.
+
+* In this page:
+ * [Include timings in a query](../../../../client-api/session/querying/debugging/query-timings#include-timings-in-a-query)
+ * [View timings](../../../../client-api/session/querying/debugging/query-timings#view-timings)
+ * [Syntax](../../../../client-api/session/querying/debugging/query-timings#syntax)
+ * [Timings in a sharded database](../../../../client-api/session/querying/debugging/query-timings#timings-in-a-sharded-database)
+
+{NOTE/}
+
+---
+
+{PANEL: Include timings in a query}
+
+{CODE-TABS}
+{CODE-TAB:php:query timing_2@ClientApi\Session\Querying\Debugging\IncludeQueryTimings.php /}
+{CODE-TAB-BLOCK:sql:RQL}
+from "Products"
+where search(Name, "Syrup") or search(Name, "Lager")
+include timings()
+{CODE-TAB-BLOCK/}
+{CODE-TABS/}
+
+{PANEL/}
+
+{PANEL: View timings}
+
+* The detailed timings can be viewed from Studio's [Query view](../../../../studio/database/queries/query-view).
+
+* Running an RQL query with `include timings()` will show an additional **Timings Tab**
+ with a graphical representation of the time spent in each query part.
+
+![Figure 1. Include timings graphical results](images/include-timings.png "Include timings results")
+
+{PANEL/}
+
+{PANEL: Syntax}
+
+{CODE:php syntax@ClientApi\Session\Querying\Debugging\IncludeQueryTimings.php /}
+
+| Parameter | Type | Description |
+|-------------|----------------|---------------|
+| **&$timings** | `QueryTimings` | A callback function (action) that takes `QueryTimings` as an argument. It will be called by the client with the resulting `QueryTimings`. You can interact with the resulting `QueryTimings` inside your callback. |
+
+{PANEL/}
+
+{PANEL: Timings in a sharded database}
+
+* In a sharded database, timings for each part are provided **per shard**.
+
+* Learn more in [timings in a sharded database](../../../../sharding/querying#timing-queries).
+
+{PANEL/}
diff --git a/Documentation/6.0/Samples/php/ClientApi/session/Querying/Debugging/IncludeQueryTimings.php b/Documentation/6.0/Samples/php/ClientApi/session/Querying/Debugging/IncludeQueryTimings.php
new file mode 100644
index 0000000000..ff7d0a0d23
--- /dev/null
+++ b/Documentation/6.0/Samples/php/ClientApi/session/Querying/Debugging/IncludeQueryTimings.php
@@ -0,0 +1,42 @@
+openSession();
+ try {
+ # region timing_2
+ $timings = new QueryTimings();
+
+ /** @var array $resultsWithTimings */
+ $resultsWithTimings = $session->advanced()->documentQuery(Product::class)
+ ->timings($timings)
+ ->search("Name", "Syrup")
+ ->toList();
+
+ /** @var array $timingsMap */
+ $timingsMap = $timings->getTimings();
+ # endregion
+ } finally {
+ $session->close();
+ }
+ } finally {
+ $store->close();
+ }
+ }
+}