From 71407940c5364dfebbfba1e2450cf392ec937f88 Mon Sep 17 00:00:00 2001 From: reebhub Date: Mon, 14 Oct 2024 04:10:22 +0300 Subject: [PATCH] added PHP markdown and sample files, mainly to ver 5.4 --- .../query-vs-document-query.dotnet.markdown | 8 +- .../query-vs-document-query.js.markdown | 2 +- .../query-vs-document-query.php.markdown | 87 ++++ .../query-vs-document-query.python.markdown | 2 +- .../what-is-document-query.js.markdown | 2 +- .../what-is-document-query.php.markdown | 169 +++++++ ...how-to-count-query-results.dotnet.markdown | 2 +- .../how-to-count-query-results.js.markdown | 2 +- .../how-to-count-query-results.php.markdown | 52 +++ ...how-to-count-query-results.python.markdown | 6 +- .../how-to-customize-query.dotnet.markdown | 10 +- .../how-to-customize-query.js.markdown | 54 +-- .../how-to-customize-query.php.markdown | 232 +++++++++ .../how-to-filter-by-field.php.markdown | 67 +++ ...-filter-by-non-existing-field.php.markdown | 117 +++++ .../how-to-get-query-statistics.js.markdown | 26 +- .../how-to-get-query-statistics.php.markdown | 64 +++ ...o-perform-a-faceted-search.dotnet.markdown | 4 +- ...ow-to-perform-a-faceted-search.js.markdown | 4 +- ...w-to-perform-a-faceted-search.php.markdown | 25 + ...how-to-perform-group-by-query.php.markdown | 137 ++++++ ...-to-perform-queries-lazily.dotnet.markdown | 2 +- .../how-to-perform-queries-lazily.js.markdown | 4 +- ...how-to-perform-queries-lazily.php.markdown | 75 +++ .../how-to-project-query-results.php.markdown | 225 +++++++++ ...w-to-project-query-results.python.markdown | 6 +- .../querying/how-to-query.dotnet.markdown | 68 +-- .../session/querying/how-to-query.js.markdown | 62 +-- .../querying/how-to-query.php.markdown | 354 ++++++++++++++ .../querying/how-to-query.python.markdown | 2 +- .../how-to-use-intersect.php.markdown | 28 ++ .../how-to-use-morelikethis.php.markdown | 71 +++ ...w-to-work-with-suggestions.dotnet.markdown | 48 +- .../how-to-work-with-suggestions.js.markdown | 46 +- .../how-to-work-with-suggestions.php.markdown | 168 +++++++ .../querying/sort-query-results.js.markdown | 20 +- .../querying/sort-query-results.php.markdown | 290 ++++++++++++ .../session/Querying/CountQueryResults.php | 32 ++ .../DocumentQuery/QueryVsDocumentQuery.php | 64 +++ .../DocumentQuery/WhatIsDocumentQuery.php | 78 ++++ .../Querying/FilterByNonExistingField.php | 106 +++++ .../session/Querying/HowToCustomize.php | 178 +++++++ .../session/Querying/HowToFilterByField.php | 36 ++ .../Querying/HowToGetQueryStatistics.php | 59 +++ .../Querying/HowToPerformFacetedSearch.php | 339 ++++++++++++++ .../Querying/HowToPerformGroupByQuery.php | 352 ++++++++++++++ .../Querying/HowToPerformQueriesLazily.php | 122 +++++ .../Querying/HowToProjectQueryResults.php | 241 ++++++++++ .../ClientApi/session/Querying/HowToQuery.php | 144 ++++++ .../session/Querying/HowToUseIntersect.php | 54 +++ .../Querying/HowToWorkWithSuggestions.php | 115 +++++ .../session/Querying/MakeSpatialQuery.php | 196 ++++++++ .../session/Querying/MoreLikeThis.php | 156 +++++++ .../session/Querying/SortQueryResults.php | 440 ++++++++++++++++++ ...w-to-project-query-results.dotnet.markdown | 6 +- .../how-to-project-query-results.js.markdown | 46 +- .../how-to-project-query-results.php.markdown | 236 ++++++++++ ...w-to-project-query-results.python.markdown | 6 +- .../querying/sort-query-results.php.markdown | 290 ++++++++++++ .../Querying/HowToProjectQueryResults.php | 241 ++++++++++ .../session/Querying/MakeSpatialQuery.php | 196 ++++++++ .../session/Querying/SortQueryResults.php | 440 ++++++++++++++++++ 62 files changed, 6496 insertions(+), 218 deletions(-) create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-field.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-non-existing-field.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-group-by-query.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-intersect.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-morelikethis.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.php.markdown create mode 100644 Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/CountQueryResults.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/QueryVsDocumentQuery.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/WhatIsDocumentQuery.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/FilterByNonExistingField.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToCustomize.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToFilterByField.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToGetQueryStatistics.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformFacetedSearch.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformGroupByQuery.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformQueriesLazily.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToQuery.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToUseIntersect.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToWorkWithSuggestions.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/MoreLikeThis.php create mode 100644 Documentation/5.4/Samples/php/ClientApi/session/Querying/SortQueryResults.php create mode 100644 Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown create mode 100644 Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown create mode 100644 Documentation/6.0/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php create mode 100644 Documentation/6.0/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php create mode 100644 Documentation/6.0/Samples/php/ClientApi/session/Querying/SortQueryResults.php diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.dotnet.markdown index baecd36e0e..7df723522c 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.dotnet.markdown @@ -22,7 +22,7 @@ {PANEL: API support} -__Query__: +**Query**: * The `Query` API supports LINQ, the essential data access solution in .NET. @@ -35,7 +35,7 @@ __Query__: --- -__DocumentQuery__: +**DocumentQuery**: * `DocumentQuery` does Not support LINQ. @@ -49,7 +49,7 @@ __DocumentQuery__: {NOTE: } -__Note__: +**Note**: `Query` and `DocumentQuery` can be converted to one another. This enables you to take advantage of all available API methods & extensions. @@ -61,7 +61,7 @@ See [Convert between DocumentQuery and Query](../../../../client-api/session/que {PANEL: Immutability} -* `Query` is __immutable__ while `DocumentQuery` is __mutable__. +* `Query` is **immutable** while `DocumentQuery` is **mutable**. You might get different results if you try to *reuse* a query. --- diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.js.markdown index 8f53f32bc2..e77aad9df8 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.js.markdown @@ -4,7 +4,7 @@ {NOTE: } -* The Node.js client provides a __unified API__ for querying documents via the `session.query()` method. +* The Node.js client provides a **unified API** for querying documents via the `session.query()` method. All available methods for the session's _query_ method are listed [here](../../../../client-api/session/querying/how-to-query#query-api). * The `query` method is essentially a shorthand for invoking the `documentQuery` method. diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.php.markdown new file mode 100644 index 0000000000..0cff743b05 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.php.markdown @@ -0,0 +1,87 @@ +# Query vs DocumentQuery + +--- + +{NOTE: } + +* RavenDB Queries can be executed using `query` or `document_query`, or by passing + [RQL](../../../../client-api/session/querying/what-is-rql) directly to the server + via `raw_query`. + Learn more in [Query Overview](../../../../client-api/session/querying/how-to-query). + +* In the PHP client API, `query` methods and their equivalent `documentQuery` methods + provide the same functionality. (This is different from the C# client implementation, + which often provides different functionality for `Query` methods and their `DocumentQuery` + counterparts.) + The PHP documentation therefore often provides `query` usage samples without adding + `documentQuery` examples as well. + +* In this page: + * [API support](../../../../client-api/session/querying/document-query/query-vs-document-query#api-support) + * [`query `and `documentQuery` equivalents](../../../../client-api/session/querying/document-query/query-vs-document-query#queryand-documentquery-equivalents) + +{NOTE/} + +--- + +{PANEL: API support} + +* `query` and `documentQquery` queries are translated to RQL and sent to the server. +* Available _query_ methods are listed [here](../../../../client-api/session/querying/how-to-query#custom-methods). +* Available _documentQuery_ methods and extensions are listed [here](../../../../client-api/session/querying/document-query/what-is-document-query#custom-methods-and-extensions). + +{PANEL/} + +{PANEL: `query `and `documentQuery` equivalents} + +#### 1. + +{CODE:php query_1a@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +is equivalent to: + +{CODE:php query_1b@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +--- + +#### 2. + +{CODE:php query_2a@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +is equivalent to: + +{CODE:php query_2b@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +--- + +#### 3. + +{CODE:php query_3a@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +is equivalent to: + +{CODE:php query_3b@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +--- + +#### 4. + +{CODE:php query_4a@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +is equivalent to: + +{CODE:php query_4b@ClientApi\Session\Querying\DocumentQuery\QueryVsDocumentQuery.php /} + +{PANEL/} + +## Related Articles + +### Session + +- [Query Overview](../../../../client-api/session/querying/how-to-query) +- [What is a Document Query](../../../../client-api/session/querying/document-query/what-is-document-query) +- [How to use Lucene](../../../../client-api/session/querying/document-query/how-to-use-lucene) + +### Indexes + +- [Querying an Index](../../../../indexes/querying/query-index) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.python.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.python.markdown index 7c4b7905fe..a0ac85530c 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.python.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/query-vs-document-query.python.markdown @@ -13,7 +13,7 @@ provide the same functionality. (This is different from the C# client implementation, which often provides different functionality for `Query` methods and their `DocumentQuery` counterparts.) - Therefore the Python documentation often provides `query` usage samples without adding + The Python documentation therefore often provides `query` usage samples without adding `document_query` examples as well. * In this page: diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.js.markdown index 26d9d3085d..ca964fa624 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.js.markdown @@ -5,7 +5,7 @@ {NOTE: } * In contrast to the .NET client, - the Node.js client provides a __unified API__ for querying documents via the `session.query()` method. + the Node.js client provides a **unified API** for querying documents via the `session.query()` method. * The `query` method is essentially a shorthand for invoking the `documentQuery` method. See examples of those equivalent calls in [query vs documentQuery](../../../../client-api/session/querying/document-query/query-vs-document-query). diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.php.markdown new file mode 100644 index 0000000000..e5c6546b28 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/document-query/what-is-document-query.php.markdown @@ -0,0 +1,169 @@ +# What is a Document Query? + +--- + +{NOTE: } + +* RavenDB queries can be executed via `query`, `documentQuery` or directly using `RQL`. + Learn more in [Query Overview](../../../../client-api/session/querying/how-to-query). + +* See [Query -vs- documentQuery](../../../../client-api/session/querying/document-query/query-vs-document-query) + for additional details. + +* In this page: + * [documentQuery examples](../../../../client-api/session/querying/document-query/what-is-document-query#documentquery-examples) + * [Custom methods](../../../../client-api/session/querying/document-query/what-is-document-query#custom-methods) + * [Syntax](../../../../client-api/session/querying/document-query/what-is-document-query#syntax) + +{NOTE/} + +--- + +{PANEL: documentQuery examples} + +#### Query collection - no filtering + +{CODE-TABS} +{CODE-TAB:php:documentQuery documentQuery_2@ClientApi\Session\Querying\DocumentQuery\WhatIsDocumentQuery.php /}) +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +--- + +#### Query collection - with filtering + +{CODE-TABS} +{CODE-TAB:php:documentQuery documentQuery_3@ClientApi\Session\Querying\DocumentQuery\WhatIsDocumentQuery.php /}) +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" where FirstName == "Robert" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +--- + +#### Query an index + +* Using a Path string + {CODE:php documentQuery_4@ClientApi\Session\Querying\DocumentQuery\WhatIsDocumentQuery.php /}) + +* Using an index Class + {CODE:php documentQuery_5@ClientApi\Session\Querying\DocumentQuery\WhatIsDocumentQuery.php /}) + +{NOTE: } +Please refer to [Querying an index](../../../../indexes/querying/query-index#session.advanced.documentquery) for examples of querying an index using a documentQuery. +{NOTE/} + +{PANEL/} + +{PANEL: Custom Methods} + +{NOTE: } + +Several methods share the same functionality as their `query` counterparts. +Refer to the corresponding documentation articles, marked with links starting with "[Query]" in the list below. + +{NOTE/} + +Available custom methods: + +- AddOrder +- [query] [afterQueryExecuted](../../../../client-api/session/querying/how-to-customize-query#afterqueryexecuted) +- [query] [afterStreamExecuted](../../../../client-api/session/querying/how-to-customize-query#afterstreamexecuted) +- [query] [aggregateBy](../../../../client-api/session/querying/how-to-perform-a-faceted-search) +- [query] [aggregateUsing](../../../../client-api/session/querying/how-to-perform-a-faceted-search) +- andAlso +- [query] [beforeQueryExecuted](../../../../client-api/session/querying/how-to-customize-query#beforequeryexecuted) +- [boost](../../../../client-api/session/querying/text-search/boost-search-results) +- closeSubclause +- cmpXchg +- containsAll +- containsAny +- [count](../../../../client-api/session/querying/how-to-count-query-results) +- [countLazily](../../../../client-api/session/querying/how-to-perform-queries-lazily#lazy-count-query) +- distinct +- explainScores +- first +- firstOrDefault +- fuzzy +- getIndexQuery +- getQueryResult +- [groupBy](../../../../client-api/session/querying/how-to-perform-group-by-query) +- [groupByArrayValues](../../../../client-api/session/querying/how-to-perform-group-by-query#by-array-values) +- [groupByArrayContent](../../../../client-api/session/querying/how-to-perform-group-by-query#by-array-content) +- [query] [Highlight](../../../../client-api/session/querying/text-search/highlight-query-results) +- include +- includeExplanations +- intersect +- invokeAfterQueryExecuted +- invokeAfterStreamExecuted +- [query] [lazily](../../../../client-api/session/querying/how-to-perform-queries-lazily) +- [longCount](../../../../client-api/session/querying/how-to-count-query-results) +- moreLikeThis +- negateNext +- [not](../../../../client-api/session/querying/document-query/how-to-use-not-operator) +- [query] [noCaching](../../../../client-api/session/querying/how-to-customize-query#nocaching) +- [query] [noTracking](../../../../client-api/session/querying/how-to-customize-query#notracking) +- ofType +- openSubclause +- [orderBy](../../../../client-api/session/querying/sort-query-results) +- [orderByDescending](../../../../client-api/session/querying/sort-query-results) +- [query] [orderByDistance](../../../../client-api/session/querying/how-to-make-a-spatial-query#orderByDistance) +- [query] [orderByDistanceDescending](../../../../client-api/session/querying/how-to-make-a-spatial-query#orderByDistanceDesc) +- [orderByScore](../../../../client-api/session/querying/sort-query-results#order-by-score) +- [orderByScoreDescending](../../../../client-api/session/querying/sort-query-results#order-by-score) +- orElse +- [query] [projection](../../../../client-api/session/querying/how-to-customize-query#projection) +- proximity +- [query] [randomOrdering](../../../../client-api/session/querying/how-to-customize-query#randomordering) +- [query] [relatesToShape](../../../../client-api/session/querying/how-to-make-a-spatial-query#search-by-shape) +- [search](../../../../client-api/session/querying/text-search/full-text-search) +- selectFields +- selectTimeSeries +- single +- singleOrDefault +- skip +- [query] [spatial](../../../../client-api/session/querying/how-to-make-a-spatial-query) +- statistics +- [suggestUsing](../../../../client-api/session/querying/how-to-work-with-suggestions) +- take +- [query] [timings](../../../../client-api/session/querying/how-to-customize-query#timings) +- usingDefaultOperator +- [query] [waitForNonStaleResults](../../../../client-api/session/querying/how-to-customize-query#waitfornonstaleresults) +- where +- whereBetween +- [whereEndsWith](../../../../client-api/session/querying/text-search/ends-with-query) +- whereEquals +- [whereExists](../../../../client-api/session/querying/how-to-filter-by-field) +- whereGreaterThan +- whereGreaterThanOrEqual +- whereIn +- whereLessThan +- whereLessThanOrEqual +- [whereLucene](../../../../client-api/session/querying/document-query/how-to-use-lucene) +- whereNotEquals +- [whereRegex](../../../../client-api/session/querying/text-search/using-regex) +- [whereStartsWith](../../../../client-api/session/querying/text-search/starts-with-query) +- withinRadiusOf + +{PANEL/} + +{PANEL: Syntax} + +The definition for `documentQuery` is listed in the [Syntax section](../../../../client-api/session/querying/how-to-query#syntax) +of the [Query Overview](../../../../client-api/session/querying/how-to-query). + +{PANEL/} + +## Related Articles + +### Session + +- [Query overview](../../../../client-api/session/querying/how-to-query) +- [How to Use Lucene](../../../../client-api/session/querying/document-query/how-to-use-lucene) + +### Querying + +- [Query vs documentQuery](../../../../client-api/session/querying/document-query/query-vs-document-query) +- [Projections](../../../../indexes/querying/projections) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.dotnet.markdown index 88257d00ef..f17060611c 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.dotnet.markdown @@ -4,7 +4,7 @@ {NOTE: } -* The following options are available to __count query results__: +* The following options are available to **count query results**: * [Count](../../../client-api/session/querying/how-to-count-query-results#count) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.js.markdown index 4ef7bbe2d5..7ff4a38f6f 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.js.markdown @@ -4,7 +4,7 @@ {NOTE: } -* The following options are available to __count query results__: +* The following options are available to **count query results**: * [Count](../../../client-api/session/querying/how-to-count-query-results#count) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.php.markdown new file mode 100644 index 0000000000..cd4393d286 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.php.markdown @@ -0,0 +1,52 @@ +# Count Query Results + +--- + +{NOTE: } + +* The following options are available to **count query results**: + + * [`Count`](../../../client-api/session/querying/how-to-count-query-results#count) + * [Get number of results from query stats](../../../client-api/session/querying/how-to-count-query-results#get-count-from-query-stats) + +{NOTE/} + +--- + +{PANEL: `Count`} + +Count query results using the `Count` method. + +{CODE-TABS} +{CODE-TAB:php:documentQuery count_3@ClientApi\Session\Querying\CountQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Orders" +where ShipTo.Country == "UK" limit 0, 0 + +// The RQL generated will trigger query execution +// however, no documents are returned (limit is set 0) +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Get count from query stats} + +When executing a query, you can retrieve the query statistics that include the total number of results. +Learn more in [Get Query Statistics](../../../client-api/session/querying/how-to-get-query-statistics). + +{PANEL/} + +## Related Articles + +### Client API + +- [Query overview](../../../client-api/session/querying/how-to-query) +- [What is a Document Query](../../../client-api/session/querying/document-query/what-is-document-query) +- [Filter by Field Presence](../../../client-api/session/querying/how-to-filter-by-field) +- [Get Query Statistics](../../../client-api/session/querying/how-to-get-query-statistics) + +### Querying + +- [Filtering](../../../indexes/querying/filtering) +- [RQL - Raven Query Language](../../../client-api/session/querying/what-is-rql) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.python.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.python.markdown index a58dd3df2d..7844353d56 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.python.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-count-query-results.python.markdown @@ -4,7 +4,7 @@ {NOTE: } -* The following options are available to __count query results__: +* The following options are available to **count query results**: * [`count`](../../../client-api/session/querying/how-to-count-query-results#count) * [Get number of results from query stats](../../../client-api/session/querying/how-to-count-query-results#get-count-from-query-stats) @@ -37,7 +37,7 @@ To do this, define a callback function that takes `QueryStatistics` as an argume logic you want to apply. {CODE-BLOCK:python} -def __statistics_callback(statistics: QueryStatistics) -> None: +def **statistics_callback(statistics: QueryStatistics) -> None: # Read and interact with QueryStatistics here total_results = statistics.total_results duration_milliseconds = statistics.duration_in_ms @@ -50,7 +50,7 @@ Then pass your function as an argument to the `query.statistics` method and use employees = list( session.query(object_type=Employee) .where_equals("first_name", "Robert") - .statistics(__statistics_callback) + .statistics(**statistics_callback) ) {CODE-BLOCK/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.dotnet.markdown index 881630655a..f9c55f0359 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.dotnet.markdown @@ -190,11 +190,13 @@ {PANEL: Projection} -* By default, when [querying an index](../../../indexes/querying/query-index), and projecting query results - (projecting means the query returns only specific document fields instead of the full document) - then the server will try to retrieve the fields' values from the fields [stored in the index](../../../indexes/storing-data-in-index). +* By default, when [querying an index](../../../indexes/querying/query-index) and projecting query results, + the server will try to retrieve field values from the fields [stored in the index](../../../indexes/storing-data-in-index). + {NOTE: } + Projecting means the query returns only specific document fields instead of the full document. + {NOTE/} -* If the index does Not store those fields then the fields' values will be retrieved from the documents. +* If the index does Not store these fields, the field values will be retrieved from the documents. * Use the `Projection` method to customize and modify this behavior. diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.js.markdown index 58d177e1e8..c0f61f381a 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.js.markdown @@ -4,8 +4,8 @@ {NOTE: } -* The following query customization methods that are available for the __.NET client__ under `IDocumentQueryCustomization` - are also available in the __Node.js client__. +* The following query customization methods that are available for the **.NET client** under `IDocumentQueryCustomization` + are also available in the **Node.js client**. * These methods can be used for both a dynamic-query and an index-query. @@ -33,7 +33,7 @@ {NOTE: } -__Example__ +**Example** {CODE-TABS} {CODE-TAB:nodejs:Query customize_1_0@client-api\session\querying\howToCustomize.js /} @@ -44,13 +44,13 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_1_1@client-api\session\querying\howToCustomize.js /} | Parameters | Type | Description | |------------------|-----------------|---------------------------------------------------------------------------------------------------------------------------------------| -| __eventHandler__ | (query) => void | A callback method that is invoked when the `beforeQueryExecuted` event is emitted.
The passed query param is of type `IndexQuery`. | +| **eventHandler** | (query) => void | A callback method that is invoked when the `beforeQueryExecuted` event is emitted.
The passed query param is of type `IndexQuery`. | {NOTE/} @@ -62,7 +62,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE:nodejs customize_2_0@client-api\session\querying\howToCustomize.js /} @@ -70,13 +70,13 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_2_1@client-api\session\querying\howToCustomize.js /} | Parameters | Type | Description | |--------------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------| -| __eventHandler__ | (queryResult) => void | A callback method that is invoked when the `afterQueryExecuted` event is emitted.
The passed query param is of type `QueryResult`. | +| **eventHandler** | (queryResult) => void | A callback method that is invoked when the `afterQueryExecuted` event is emitted.
The passed query param is of type `QueryResult`. | {NOTE/} @@ -90,7 +90,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE:nodejs customize_3_0@client-api\session\querying\howToCustomize.js /} @@ -98,7 +98,7 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_3_1@client-api\session\querying\howToCustomize.js /} @@ -116,7 +116,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE:nodejs customize_4_0@client-api\session\querying\howToCustomize.js /} @@ -124,7 +124,7 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_4_1@client-api\session\querying\howToCustomize.js /} @@ -150,7 +150,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE-TABS} {CODE-TAB:nodejs:Query customize_5_0@client-api\session\querying\howToCustomize.js /} @@ -161,15 +161,15 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_5_1@client-api\session\querying\howToCustomize.js /} | Parameters | Type | Description | |------------------------|----------|----------------------------------------------------------------| -| __properties__ | string[] | Fields' names for which to fetch values | -| __projectionClass__ | object | The projected results class | -| __projectionBehavior__ | string | The requested projection behavior, see available options below | +| **properties** | string[] | Fields' names for which to fetch values | +| **projectionClass** | object | The projected results class | +| **projectionBehavior** | string | The requested projection behavior, see available options below | * `Default` Retrieve values from the stored index fields when available. @@ -200,7 +200,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE:nodejs customize_6_0@client-api\session\querying\howToCustomize.js /} @@ -208,13 +208,13 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_6_1@client-api\session\querying\howToCustomize.js /} | Parameters | Type | Description | |------------|--------|--------------------------------------------------------------------------------------------------------| -| __seed__ | string | Order the search results randomly using this seed.
Useful when executing repeated random queries. | +| **seed** | string | Order the search results randomly using this seed.
Useful when executing repeated random queries. | {NOTE/} @@ -230,7 +230,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE:nodejs customize_7_0@client-api\session\querying\howToCustomize.js /} @@ -238,18 +238,18 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_7_1@client-api\session\querying\howToCustomize.js /} | Parameters | 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 | {NOTE/} @@ -273,7 +273,7 @@ __Syntax__ {NOTE: } -__Example__ +**Example** {CODE:nodejs customize_8_0@client-api\session\querying\howToCustomize.js /} @@ -281,7 +281,7 @@ __Example__ {NOTE: } -__Syntax__ +**Syntax** {CODE:nodejs customize_8_1@client-api\session\querying\howToCustomize.js /} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.php.markdown new file mode 100644 index 0000000000..bbacbeb1dd --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-customize-query.php.markdown @@ -0,0 +1,232 @@ +# Customize Query + +--- + +{NOTE: } + +* Use the below methods to set customization options on a specific [query](../../../client-api/session/querying/how-to-query). + Customizations can be set for both **dynamic** and **index** queries. + +* A query can also be customized on the store or session level by + [subscribing to `OnBeforeQuery`](../../../client-api/session/how-to/subscribe-to-events). + +* Available customization methods : + - [`addBeforeQueryExecutedListener` and `removeBeforeQueryExecutedListener`](../../../client-api/session/querying/how-to-customize-query#addbeforequeryexecutedlistener-and-removebeforequeryexecutedlistener) + - [`addAfterQueryExecutedListener` and `removeAfterQueryExecutedListener`](../../../client-api/session/querying/how-to-customize-query#addafterqueryexecutedlistener-and-removeafterqueryexecutedlistener) + - [`noCaching`](../../../client-api/session/querying/how-to-customize-query#nocaching) + - [`noTracking`](../../../client-api/session/querying/how-to-customize-query#notracking) + - [Projection](../../../client-api/session/querying/how-to-customize-query#randomordering) + - [`randomOrdering`](../../../client-api/session/querying/how-to-customize-query#randomordering) + - [`waitForNonStaleResults`](../../../client-api/session/querying/how-to-customize-query#waitfornonstaleresults) +* [Methods return value](../../../client-api/session/querying/how-to-customize-query#methods-return-value) + + +{NOTE/} + +--- + +{PANEL: `addBeforeQueryExecutedListener` and `removeBeforeQueryExecutedListener`} + +* Use these methods to customize the query just before it is executed. + +**Example** + +{CODE:php customize_1_1@ClientApi\Session\Querying\HowToCustomize.php /} + +{NOTE: } + +**Syntax** + +{CODE:php customize_1_0@ClientApi\Session\Querying\HowToCustomize.php /} + +| Parameters | Type | Description | +|------------| ---- |------------------------------------------------------| +| **$action** | `Closure` | An _$action_ method that operates on the query | + +{NOTE/} + +{PANEL/} + +{PANEL: `addAfterQueryExecutedListener` and `removeAfterQueryExecutedListener`} + +* Use these methods to access the raw query result after it is executed. + +**Example** + +{CODE:php customize_1_1_0@ClientApi\Session\Querying\HowToCustomize.php /} + +{NOTE: } + +**Syntax** + +{CODE:php customize_1_0_0@ClientApi\Session\Querying\HowToCustomize.php /} + +| Parameters | Type | Description | +|------------| ---- |-------------| +| **$action** | `Closure` | An _Action_ method that receives the raw query result | + +{NOTE/} + +{PANEL/} + +{PANEL: `noCaching`} + +* By default, query results are cached. + +* You can use the `noCaching` customization to disable query caching. + +* Learn more in [disable caching per session](../../../client-api/session/configuration/how-to-disable-caching). + +**Example** + +{CODE:php customize_2_1@ClientApi\Session\Querying\HowToCustomize.php /} + +**Syntax** + +{CODE:php customize_2_0@ClientApi\Session\Querying\HowToCustomize.php /} + +{PANEL/} + +{PANEL: `noTracking`} + +* By default, the [session](../../../client-api/session/what-is-a-session-and-how-does-it-work) tracks all changes made to all entities that it has either loaded, stored, or queried for. + +* You can use the `noTracking` customization to disable entity tracking. + +* See [disable entity tracking](../../../client-api/session/configuration/how-to-disable-tracking) for all other options. + +**Example** + +{CODE:php customize_3_1@ClientApi\Session\Querying\HowToCustomize.php /} + +**Syntax** + +{CODE:php customize_3_0@ClientApi\Session\Querying\HowToCustomize.php /} + +{PANEL/} + +{PANEL: Projection} + +* By default, when [querying an index](../../../indexes/querying/query-index) and projecting query results, + the server will try to retrieve field values from the fields [stored in the index](../../../indexes/storing-data-in-index). + {NOTE: } + Projecting means the query returns only specific document fields instead of the full document. + {NOTE/} + +* If the index does Not store these fields, the field values will be retrieved from the documents. + +* Use the `projection` method to customize and modify this behavior. + +* Note: + Entities resulting from a projecting query are Not tracked by the session. + Learn more about projections in: + + * [Project index query results](../../../indexes/querying/projections) + * [Project dynamic query results](../../../client-api/session/querying/how-to-project-query-results) + +**Example** + +{CODE:php projectionbehavior_query@ClientApi\Session\Querying\HowToCustomize.php /} + +**Syntax** + +{CODE:php projectionbehavior@ClientApi\Session\Querying\HowToCustomize.php /} + +* `default` + Retrieve values from the stored index fields when available. + If fields are not stored then get values from the document, + a field that is not found in the document is skipped. +* `fromIndex` + Retrieve values from the stored index fields when available. + A field that is not stored in the index is skipped. +* `fromIndexOrThrow` + Retrieve values from the stored index fields when available. + An exception is thrown if the index does not store the requested field. +* `fromDocument` + Retrieve values directly from the documents store. + A field that is not found in the document is skipped. +* `fromDocumentOrThrow` + Retrieve values directly from the documents store. + An exception is thrown if the document does not contain the requested field. + +{PANEL/} + +{PANEL: `randomOrdering`} + +* Use `randomOrdering` to order the query results randomly. + +* More ordering options are available in this [Sorting](../../../client-api/session/querying/sort-query-results) article. + +**Example** + +{CODE:php customize_4_1@ClientApi\Session\Querying\HowToCustomize.php /} + +**Syntax** + +{CODE:php customize_4_0@ClientApi\Session\Querying\HowToCustomize.php /} + +| Parameters | Type | Description | +|------------| ------------- |---------------------------------------------------------------------------------------------------| +| **$seed** | `?string` | Order the search results randomly using this seed.
Useful when executing repeated random queries. | + +{PANEL/} + +{PANEL: `waitForNonStaleResults`} + +* All queries in RavenDB provide results using an index, even when you don't specify one. + See detailed explanation in [Queries always provide results using an index](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). + +* Use `waitForNonStaleResults` to instruct the query to wait for non-stale results from the index. + +* A `TimeoutException` will be thrown if the query is not able to return non-stale results within the specified + (or default) timeout. + +* Learn more about stale results in [stale indexes](../../../indexes/stale-indexes). + +{NOTE: } + +**Example** + +{CODE:php customize_8_1@ClientApi\Session\Querying\HowToCustomize.php /} + +{NOTE/} + +{NOTE: } + +**Syntax** + +{CODE:php customize_8_0@ClientApi\Session\Querying\HowToCustomize.php /} + +| Parameters | Type | Description | +|------------| ------------- |-----------| +| **$waitTimeout** | `Duration` | Time to wait for non-stale results.
Default is 15 seconds. | + +{NOTE/} + +{PANEL/} + +{PANEL: Methods return value} + +All of the above customization methods return the following: + +| Return value | | +|-----------------------------| ----- | +| `DocumentQueryCustomizationInterface` | Returns self for easier method chaining | + +{PANEL/} + +## Related Articles + +### Session + +- [How to Query](../../../client-api/session/querying/how-to-query) +- [How to Subscribe to Events](../../../client-api/session/how-to/subscribe-to-events) + +### Configuration + +- [Conventions](../../../client-api/configuration/conventions) +- [Querying](../../../client-api/configuration/querying) + +### Indexes + +- [Stale Indexes](../../../indexes/stale-indexes) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-field.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-field.php.markdown new file mode 100644 index 0000000000..2013699558 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-field.php.markdown @@ -0,0 +1,67 @@ +# Filter by Field Presence + +--- + +{NOTE: } + +* To query for documents that contain a particular field, use the `whereExists` extension method. + +* A document that doesn't contain the specified field will be excluded from the query results. + +* In this page: + * [Filter by field name](../../../client-api/session/querying/how-to-filter-by-field#filter-by-field-name) + * [Filter by field path](../../../client-api/session/querying/how-to-filter-by-field#filter-by-field-path) + * [Syntax](../../../client-api/session/querying/how-to-filter-by-field#syntax) + +{NOTE/} + +--- + +{PANEL: Filter by field name } + +{CODE-TABS} +{CODE-TAB:php:whereExists whereexists_2@ClientApi\Session\Querying\HowToFilterByField.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Only documents that contain field 'FirstName' will be returned + +from Employees +where exists("FirstName") +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Filter by field path } + +{CODE-TABS} +{CODE-TAB:php:whereExists whereexists_3@ClientApi\Session\Querying\HowToFilterByField.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Only documents that contain the 'Latitude' property in the specified path will be returned + +from Employees +where exists("Address.Location.Latitude") +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Syntax} + +{CODE:php whereexists_1@ClientApi\Session\Querying\HowToFilterByField.php /} + +| Parameters | Type | Description | +|----------------|-----------|----------------------------------------------------| +| **$fieldName** | `?string` | The name / path of the document field to filter by | + +{PANEL/} + +## Related Articles + +### Client API + +- [What is a Document Query](../../../client-api/session/querying/document-query/what-is-document-query) + +### Indexes + +- [Querying: Filtering](../../../indexes/querying/filtering) +- [Query vs DocumentQuery](../../../client-api/session/querying/document-query/query-vs-document-query) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-non-existing-field.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-non-existing-field.php.markdown new file mode 100644 index 0000000000..de0bace9c9 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-filter-by-non-existing-field.php.markdown @@ -0,0 +1,117 @@ +# Filter by Non-Existing Field + +--- + +{NOTE: } + +* There are situations where new fields are added to some documents in a collection over time. +* To find documents that are missing the newly added fields you can either: + * [Query the collection (dynamic query)](../../../client-api/session/querying/how-to-filter-by-non-existing-field#query-the-collection-(dynamic-query)) + * [Query a static index](../../../client-api/session/querying/how-to-filter-by-non-existing-field#query-a-static-index) + * [Use Studio to run an RQL Query](../../../client-api/session/querying/how-to-filter-by-non-existing-field#use-studio-to-run-an-rql-query) + +---- + +{NOTE/} + +--- + +{PANEL: Query the collection (dynamic query)} + +To run a dynamic query over a collection and find which documents are missing a specified field, +use the `not` and `whereExists` extension methods, accessible from the [documentQuery](../../../client-api/session/querying/document-query/what-is-document-query) API, +as shown below. + +This will either create a new auto-index or add the queried field to an existing auto-index. +Learn more about the dynamic query flow [here](../../../client-api/session/querying/how-to-query#dynamicQuery). + +**Example** + +{CODE-TABS} +{CODE-TAB:php:documentQuery whereNotExists_1@ClientApi\Session\Querying\FilterByNonExistingField.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Orders" +where true and not exists("Freight") +// `not` cannot be used immediately after `where`, thus we use `where true`. +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Query a static index} + +Documents with missing fields can be searched by querying a static index. + +The index definition must contain the following document fields indexed: + +* A document field that **exists** in **all** documents of the queried collection, e.g. the _Id_ field. + Indexing this field will ensure that all the documents of this collection are indexed. +* A document field that is suspected to be **missing** from some documents of the queried collection. + +**Example** + +{CODE:php the_index@ClientApi\Session\Querying\FilterByNonExistingField.php /} + +{CODE-TABS} +{CODE-TAB:php:documentQuery whereNotexists_2@ClientApi\Session\Querying\FilterByNonExistingField.php /} +{CODE-TAB-BLOCK:sql:RQL} +from index "Orders/ByFreight" +where true and not exists("Freight") +// `not` cannot come immediately after `where`, thus we use `where true`. +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Use Studio to Run an RQL Query} + +* Documents can be searched by missing fields using Studio's [Query view](../../../studio/database/queries/query-view). + +* Use an [RQL](../../../client-api/session/querying/what-is-rql) expression such as: + {CODE-BLOCK:sql} +from "Orders" +where exists("Company") and not exists("Freight") +{CODE-BLOCK/} + +* In the `where` clause: + First search for a field that **exists** in **all** documents of the queried collection, e.g. the _Id_ field. + Then search for a field that **may be missing** from some documents of the queried collection. + + ![List Documents Without a Specified Field](images/non-existing-field-studio-rql.png "Query for documents that are missing the specified field") + + 1. **Indexes** + Click to see the Indexes menu. + 2. **Query** + Select to open the Query view. + 3. **Query editor** + Write the RQL query. + 4. **Run Query** + Click to run the query. + 5. **Index used** + The name of the auto-index created to serve this query. + You can click it to see the available Studio options for this index. + 6. **Results** + This is the list of documents that do not contain the specified 'Freight' field. + (the "Freight" Field was removed from these Northwind documents for this example.) + +{PANEL/} + +## Related Articles + +### Client API + +- [What is a Document Query](../../../client-api/session/querying/document-query/what-is-document-query) +- [How to Filter by Field Presence](../../../client-api/session/querying/how-to-filter-by-field) + +### Querying + +- [Querying: Filtering](../../../indexes/querying/filtering) +- [Query vs DocumentQuery](../../../client-api/session/querying/document-query/query-vs-document-query) +- [RQL - Raven Query Language](../../../client-api/session/querying/what-is-rql) + +--- + +### Code Walkthrough + +- [Queries - Filtering Results - Basics](https://demo.ravendb.net/demos/csharp/queries/filtering-results-basics) +- [Queries - Filtering with Multiple Conditions](https://demo.ravendb.net/demos/csharp/queries/filtering-results-multiple-conditions) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.js.markdown index 464f27e6de..c53153cd6a 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.js.markdown @@ -4,7 +4,7 @@ {NOTE: } -* Detailed __query statistics__ can be retrieved for every executed query using the `statistics` method. +* Detailed **query statistics** can be retrieved for every executed query using the `statistics` method. * Stats such as query duration, number of results, index name used in the query, and more, are returned in the `QueryStatistics` object. @@ -34,21 +34,21 @@ from "Employees" where FirstName == "Anne" | Parameter | Type | Description | |-------------------|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| __statsCallback__ | `(stats) => void` |
  • A callback function with an output parameter.
  • The parameter passed to the callback will be filled with the `QueryStatistics` object when query returns.
| +| **statsCallback** | `(stats) => void` |
  • A callback function with an output parameter.
  • The parameter passed to the callback will be filled with the `QueryStatistics` object when query returns.
| | `QueryStatistics` | | | |----------------------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| __isStale__ | `boolean` | Are the results returned by the query potentially stale | -| __durationInMs__ | `number` | Query duration on the server side in Milliseconds | -| __totalResults__ | `number` | The total count of results that matched the query | -| __longTotalResults__ | `number` | The total count of results that matched the query (same as `totalResults`) | -| __skippedResults__ | `number` | The number of results skipped by the server.
Learn more in [paging through tampered results](../../../indexes/querying/paging#paging-through-tampered-results). | -| __timestamp__ | `Date` | The time when the query results were unstale | -| __indexName__ | `string` | The name of the queried index | -| __indexTimestamp__ | `Date` | The timestamp of the queried index | -| __lastQueryTime__ | `Date` | The timestamp of the last time the index was queried | -| __resultEtag__ | `number` | Results Etag | -| __nodeTag__ | `string` | Tag of the cluster node that responded to the query | +| **isStale** | `boolean` | Are the results returned by the query potentially stale | +| **durationInMs** | `number` | Query duration on the server side in Milliseconds | +| **totalResults** | `number` | The total count of results that matched the query | +| **longTotalResults** | `number` | The total count of results that matched the query (same as `totalResults`) | +| **skippedResults** | `number` | The number of results skipped by the server.
Learn more in [paging through tampered results](../../../indexes/querying/paging#paging-through-tampered-results). | +| **timestamp** | `Date` | The time when the query results were unstale | +| **indexName** | `string` | The name of the queried index | +| **indexTimestamp** | `Date` | The timestamp of the queried index | +| **lastQueryTime** | `Date` | The timestamp of the last time the index was queried | +| **resultEtag** | `number` | Results Etag | +| **nodeTag** | `string` | Tag of the cluster node that responded to the query | {PANEL/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.php.markdown new file mode 100644 index 0000000000..5f41557bf3 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-get-query-statistics.php.markdown @@ -0,0 +1,64 @@ +# Get Query Statistics + +--- + +{NOTE: } + +* Detailed **query statistics** can be retrieved for every executed query using the `statistics` method. + +* Stats such as query duration, number of results, index name used in the query, and more, + are returned in the `QueryStatistics` object. + +* In This Page: + * [Get query statistics](../../../client-api/session/querying/how-to-get-query-statistics#get-query-statistics) + * [Syntax](../../../client-api/session/querying/how-to-get-query-statistics#syntax) + +{NOTE/} + +--- + +{PANEL: Get query statistics} + +{CODE-TABS} +{CODE-TAB:php:Query stats_3@ClientApi\Session\Querying\HowToGetQueryStatistics.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" where FirstName == "Robert" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Syntax} + +{CODE:php stats_1@ClientApi\Session\Querying\HowToGetQueryStatistics.php /} + +| Parameter | Type | Description | +|-----------|-------------------|-------------------------------------------------| +| **$stats** | `QueryStatistics` | An 'out' param for getting the query statistics | + +
+ +{CODE:php stats_2@ClientApi\Session\Querying\HowToGetQueryStatistics.php /} + +| Property | Type | Description | +|----------------------|------------------|----------------------------------------------------------| +| **$isStale** | `bool` | Are the results returned by the query potentially stale | +| **$durationInMs** | `int` | Query duration on the server side in Milliseconds | +| **$totalResults**,
**$longTotalResults** | `int` | The total count of results that matched the query.
Matching query results can also be counted using [Count](../../../client-api/session/querying/how-to-count-query-results#count). | +| **$skippedResults** | `int` | The number of results skipped by the server.
Learn more in [paging through tampered results](../../../indexes/querying/paging#paging-through-tampered-results). | +| **$timestamp** | `?DateTimeInterface` | The time when the query results were unstale | +| **$indexName** | `?string` | The name of the queried index | +| **$indexTimestamp** | `?DateTimeInterface` | The timestamp of the queried index | +| **$lastQueryTime** | `?DateTimeInterface` | The timestamp of the last time the index was queried | +| **$resultEtag** | `?int` | Results Etag | +| **$nodeTag** | `?string` | Tag of the cluster node that responded to the query | + +{PANEL/} + +## Related articles + +### Session + +- [How to query](../../../client-api/session/querying/how-to-query) +- [How to customize query](../../../client-api/session/querying/how-to-customize-query) +- [Count query results](../../../client-api/session/querying/how-to-count-query-results) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.dotnet.markdown index a71d4fea4c..5b2346cd99 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.dotnet.markdown @@ -4,11 +4,11 @@ {NOTE: } -* A __Faceted Search__ provides an efficient way to explore and navigate through large datasets or search results. +* A **Faceted Search** provides an efficient way to explore and navigate through large datasets or search results. * To make a faceted search, a static-index must be defined for the fields you want to query and apply facets on. - Please refer to article __Query by Facets__ under [Indexes > Querying > Faceted search](../../../indexes/querying/faceted-search). + Please refer to article **Query by Facets** under [Indexes > Querying > Faceted search](../../../indexes/querying/faceted-search). {NOTE/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.js.markdown index a71d4fea4c..5b2346cd99 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.js.markdown @@ -4,11 +4,11 @@ {NOTE: } -* A __Faceted Search__ provides an efficient way to explore and navigate through large datasets or search results. +* A **Faceted Search** provides an efficient way to explore and navigate through large datasets or search results. * To make a faceted search, a static-index must be defined for the fields you want to query and apply facets on. - Please refer to article __Query by Facets__ under [Indexes > Querying > Faceted search](../../../indexes/querying/faceted-search). + Please refer to article **Query by Facets** under [Indexes > Querying > Faceted search](../../../indexes/querying/faceted-search). {NOTE/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.php.markdown new file mode 100644 index 0000000000..6bdac5672b --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-a-faceted-search.php.markdown @@ -0,0 +1,25 @@ +# Perform a Faceted (Aggregated) Search + +--- + +{NOTE: } + +* A **Faceted Search** provides an efficient way to explore and navigate through large datasets or search results. + +* To make a faceted search, + a static-index must be defined for the fields you want to query and apply facets on. + Please refer to the **Query by Facets** article under [Indexes > Querying > Faceted search](../../../indexes/querying/faceted-search). + +{NOTE/} + +--- + +## Related Articles + +### Session + +- [How to Query](../../../client-api/session/querying/how-to-query) + +### Indexes + +- [Faceted Search](../../../indexes/querying/faceted-search) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-group-by-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-group-by-query.php.markdown new file mode 100644 index 0000000000..b9c5199ed2 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-group-by-query.php.markdown @@ -0,0 +1,137 @@ +# Perform Dynamic Group By Query + +Since RavenDB 4.0, the query optimizer supports dynamic group by queries and automatically creates auto map-reduce indexes. + +You can create a dynamic query that does an aggregation using the `groupBy` method. + +Supported aggregation operations include: + +- `selectKey` +- `selectSum` +- `selectCount` + +{PANEL: Group By Single Field} + +{CODE-TABS} +{CODE-TAB:php group_by_1@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by ShipTo.City +select ShipTo.City as Country, sum(Lines[].Quantity) as TotalQuantity +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Group By Multiple Fields} + +{CODE-TABS} +{CODE-TAB:php group_by_2@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by Employee, Company +select Employee as EmployeeIdentifier, Company, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Select Composite GroupBy Key} + +{CODE-TABS} +{CODE-TAB:php group_by_3@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by Employee, Company +select key() as EmployeeCompanyPair, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Group By Array} + +### By Array Values + +The following query groups by the `Product` property of the `Lines` collection, +and calculates the count per ordered products. +Underneath a fanout, an auto map-reduce index will be created to handle such a query. + +{CODE-TABS} +{CODE-TAB:php group_by_4@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by Lines[].Product +select Lines[].Product, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +Inside a single group by statement you can mix collection values and value of another property. + +{CODE-TABS} +{CODE-TAB:php group_by_5@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by Lines[].Product, ShipTo.Country +select Lines[].Product as Product, ShipTo.Country as Country, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +Grouping by multiple values from **the same** collection is supported as well: + +{CODE-TABS} +{CODE-TAB:php group_by_6@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by Lines[].Product, Lines[].Quantity +select Lines[].Product as Product, Lines[].Quantity as Quantity, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### By Array Content + +Another option is to group by array content. +The reduction key will be calculated based on all values of a collection specified in `groupBy`. + +{CODE-TABS} +{CODE-TAB:php group_by_7@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by array(Lines[].Product) +select key() as Products, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +Grouping by array content and a value of another property is supported by `documentQuery`: + +{CODE-TABS} +{CODE-TAB:php group_by_8@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by array(Lines[].Product), ShipTo.Country +select Lines[].Product as Products, ShipTo.Country as Country, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +Grouping by multiple values from **the same** collection is also supported by `documentQuery`: + +{CODE-TABS} +{CODE-TAB:php group_by_9@ClientApi\Session\Querying\HowToPerformGroupByQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +group by array(Lines[].Product), array(Lines[].Quantity) +select Lines[].Product as Products, Lines[].Quantity as Quantities, count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +## Related Articles + +### Session + +- [How to Query](../../../client-api/session/querying/how-to-query) + +### Indexes + +- [Map-Reduce Indexes](../../../indexes/map-reduce-indexes) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.dotnet.markdown index aa6fc7a409..f2d8844ee0 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.dotnet.markdown @@ -80,7 +80,7 @@ | Parameters | Type | Description | |------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------| -| __onEval__ | `Action>`
`Action>`
`Action>` | An action that will be performed on the query results
when the query is executed. | +| **onEval** | `Action>`
`Action>`
`Action>` | An action that will be performed on the query results
when the query is executed. | | Return Value | | |----------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------| diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.js.markdown index e3f01befde..f59c1b1786 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.js.markdown @@ -62,11 +62,11 @@ | Parameters | Type | Description | |------------|----------------------|--------------------------------------------------------------------------------------| -| __onEval__ | `(object[]) => void` | An action that will be performed on the query results
when the query is executed. | +| **onEval** | `(object[]) => void` | An action that will be performed on the query results
when the query is executed. | | Return Value | | |--------------|------------------------------------------------------------------| -| __object__ | A `Lazy` instance that will evaluate the query only when needed. | +| **object** | A `Lazy` instance that will evaluate the query only when needed. | {PANEL/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.php.markdown new file mode 100644 index 0000000000..8507bc4ef1 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-perform-queries-lazily.php.markdown @@ -0,0 +1,75 @@ +# Perform a Lazy Query + +--- + +{NOTE: } + +* Query execution can be deferred: the query can be defined as **Lazy**, and executed + at a later time, when its results are actually needed. + +* This article contains examples for lazy queries. Prior to reading it, please refer + to [perform requests lazily](../../../client-api/session/how-to/perform-operations-lazily) + for general knowledge about RavenDB's lazy behavior and other request types that can be + executed lazily within a session. + +* Learn more about queries in this [query overview](../../../client-api/session/querying/how-to-query). + +* In this page: + * [Lazy query](../../../client-api/session/querying/how-to-perform-queries-lazily#lazy-query) + * [Lazy count query](../../../client-api/session/querying/how-to-perform-queries-lazily#lazy-count-query) + * [Lazy suggestions query](../../../client-api/session/querying/how-to-perform-queries-lazily#lazy-suggestions-query) + * [Lazy Aggregation](../../../client-api/session/querying/how-to-perform-queries-lazily#lazy-aggregation) + * [Syntax](../../../client-api/session/querying/how-to-perform-queries-lazily#syntax) + +{NOTE/} + +--- + +{PANEL: Lazy query} + +{CODE:php lazy_2@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} + +{PANEL/} + +{PANEL: Lazy count query} + +{CODE:php lazy_5@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} + +{PANEL/} + +{PANEL: Lazy suggestions query} + +{CODE:php lazy_7@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} + +* Learn more about suggestions in [query for suggestions](../../../client-api/session/querying/how-to-work-with-suggestions). + +{PANEL/} + +{PANEL: Lazy aggregation} + +{CODE:php lazy_9@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} + +{PANEL/} + +{PANEL: Syntax} + +{CODE:php lazy_1@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} +{CODE:php lazy_4@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} +{CODE:php lazy_6@ClientApi\Session\Querying\HowToPerformQueriesLazily.php /} + +| Parameters | Type | Description | +|------------|------------------------------------------------------------------------------------| +| **$onEval** | `?Closure` | An action to perform on the query results when the query is executed | + +| Return Value | | +|------------------------------------------------------------------------| +| `Lazy` | A lazy instance that will evaluate the query only when needed | + +{PANEL/} + +## Related Articles + +### Session + +- [Query overview](../../../client-api/session/querying/how-to-query) +- [Perform requests lazily](../../../client-api/session/how-to/perform-operations-lazily) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown new file mode 100644 index 0000000000..9eb5ed336e --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown @@ -0,0 +1,225 @@ +# Project Query Results +--- + +{NOTE: } + +* Applying a projection in a query allows you to shape the query results to meet specific requirements, + delivering just the data needed instead of the original full document content. + +* This article provides examples of projecting query results when making a **dynamic-query**. + For projecting results when querying a **static-index** see [project index query results](../../../indexes/querying/projections). + +* In this page: + + * [Projections overview](../../../client-api/session/querying/how-to-project-query-results#projections-overview) + + * [Projection Methods](../../../client-api/session/querying/how-to-project-query-results#projection-methods) + * [`select`, `selectFields`](../../../client-api/session/querying/how-to-project-query-results#select,-selectfields) + * [`ofType`](../../../client-api/session/querying/how-to-project-query-results#oftype) + +{NOTE/} + +--- + +{PANEL: Projections overview} + +### What are projections: + +* A projection refers to the **transformation of query results** into a customized structure, + modifying the shape of the data returned by the server. + +* Instead of retrieving the full document from the server and then picking relevant data from it on the client, + you can request a subset of the data, specifying the document fields you want to get from the server. + +* The query can load [related documents](../../../indexes/indexing-related-documents#what-are-related-documents) and have their data merged into the projection results. + +* Objects and arrays can be projected, fields can be renamed, and any calculations can be made within the projection. + +* Content from inner objects and arrays can be projected. + An alias name can be given to the projected fields, and any calculations can be made within the projection. + +### When to use projections: + +* Projections allow you to tailor the query results specifically to your needs. + Getting specific details to display can be useful when presenting data to users or populating user interfaces. + Projection queries are also useful with [subscriptions](../../../client-api/data-subscriptions/what-are-data-subscriptions) + since all transformation work is done on the server side without having to send a lot of data over the wire. + +* Returning partial document data from the server reduces network traffic, + as clients receive only relevant data required for a particular task, enhancing overall performance. + +* Savings can be significant if you need to show just a bit of information from a large document. For example: + the size of the result when querying for all "Orders" documents where "Company" is "companies/65-A" is 19KB. + Performing the same query and projecting only the "Employee" and "OrderedAt" fields results in only 5KB. + +* However, when you need to actively work with the complete set of data on the client side, + then do use a query without a projection to retrieve the full document from the server. + +### Projections are not tracked by the session: + +* On the client side, the resulting projected entities returned by the query are Not tracked by the Session. + +* Any modification made to a projection entity will not modify the corresponding document on the server when `saveChanges` is called. + +### Projections are the final stage in the query pipeline: + +* Projections are applied as the last stage in the query pipeline, + after the query has been processed, filtered, sorted, and paged. + +* This means that the projection does Not apply to all the documents in the collection, + but only to the documents matching the query predicate. + +* Within the projection you can only filter what data will be returned from the matching documents, + but you cannot filter which documents will be returned. That has already been determined earlier in the query pipeline. + +### The cost of projections: + +* Queries in RavenDB do not allow any computation to occur during the query phase. + However, you can perform any [calculations](../../../client-api/session/querying/how-to-project-query-results#example---projection-with-calculations) + inside the projection. + +* But while calculations within a projection are allowed, having a very complex logic can impact query performance. + So RavenDB limits the total time it will spend processing a query and its projections. + Exceeding this time limit will fail the query. This is configurable, see the following configuration keys: + * [Databases.QueryTimeoutInSec](../../../server/configuration/database-configuration#databases.querytimeoutinsec) + * [Databases.QueryOperationTimeoutInSec](../../../server/configuration/database-configuration#databases.queryoperationtimeoutinsec) + +{PANEL/} + +## Projection Methods + +{PANEL: `select`, `selectFields`} + +Projections are commonly performed in PHP using the `select` and `selectFields` methods. +You can specify what fields from a document you want to retrieve and even provide complex expression. + +### Example - Projecting Individual Fields of the Document: + +{CODE-TABS} +{CODE-TAB:php projections_1@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Companies +select Name, Address.City as City, Address.Country as Country +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projecting Arrays and Objects: + +{CODE-TABS} +{CODE-TAB:php projections_2@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +select ShipTo, Lines[].ProductName as Products +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with expression: + +{CODE-TABS} +{CODE-TAB:php projections_3@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" as e +select { + FullName: e.FirstName + " " + e.LastName +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Calculation: + +{CODE-TABS} +{CODE-TAB:php projections_4@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Orders" as o +select { + Total : o.Lines.reduce( + (acc , l) => acc += l.PricePerUnit * l.Quantity, 0) +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection Using a Loaded Document: + +{CODE-TABS} +{CODE-TAB:php projections_5@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Orders" as o +load o.Company as c +select { + CompanyName: c.Name, + ShippedAt: o.ShippedAt +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Dates: + +{CODE-TABS} +{CODE-TAB:php projections_6@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Employees as e +select { + DayOfBirth : new Date(Date.parse(e.Birthday)).getDate(), + MonthOfBirth : new Date(Date.parse(e.Birthday)).getMonth() + 1, + Age : new Date().getFullYear() - new Date(Date.parse(e.Birthday)).getFullYear() +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Raw JavaScript Code: + +{CODE-TABS} +{CODE-TAB:php projections_7@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Employees as e +select { + Date : new Date(Date.parse(e.Birthday)), + Name : e.FirstName.substr(0,3) +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Metadata: + +{CODE-TABS} +{CODE-TAB:php projections_13@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Employees as e +select { + Name : e.FirstName, + Metadata : getMetadata(e) +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: `ofType`} + +`ofType` is a client-side projection that maps results that the server returns into a given type. +This may become useful when querying an index that contains fields that are not available in the mapped type. + +### Example: + +{CODE-TABS} +{CODE-TAB:php:Sync projections_10@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB:php:Index projections_11@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TABS/} + +{PANEL/} + +## Related Articles + +### Session + +- [Query Overview](../../../client-api/session/querying/how-to-query) +- [How to Stream Query Results](../../../client-api/session/querying/how-to-stream-query-results) + +### Querying + +- [Querying an Index](../../../indexes/querying/query-index) +- [Projections](../../../indexes/querying/projections) + +### Server + +- [JavaScript Engine](../../../server/kb/javascript-engine) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown index aa96907846..b0298d5981 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown @@ -6,8 +6,8 @@ * Applying a projection in a query allows you to shape the query results to meet specific requirements, delivering just the data needed instead of the original full document content. -* This article provides examples of projecting query results when making a __dynamic-query__. - For projecting results when querying a __static-index__ see [project index query results](../../../indexes/querying/projections). +* This article provides examples of projecting query results when making a **dynamic-query**. + For projecting results when querying a **static-index** see [project index query results](../../../indexes/querying/projections). * In this page: @@ -26,7 +26,7 @@ ### What are projections: -* A projection refers to the __transformation of query results__ into a customized structure, +* A projection refers to the **transformation of query results** into a customized structure, modifying the shape of the data returned by the server. * Instead of retrieving the full document from the server and then picking relevant data from it on the client, diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.dotnet.markdown index 476129c8e5..81668a4f9b 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.dotnet.markdown @@ -5,9 +5,9 @@ {NOTE: } * Queries in RavenDB can be written with either of the following: - * __LINQ__ - when querying with the session's `Query` method. - * __Low-level API__ - when querying with the session's `DocumentQuery` method. - * __RQL__: + * **LINQ** - when querying with the session's `Query` method. + * **Low-level API** - when querying with the session's `DocumentQuery` method. + * **RQL**: * when querying with the session's `RawQuery` method. * when querying from the [Query view](../../../studio/database/queries/query-view) in Studio. @@ -16,21 +16,21 @@ --- -* All queries in RavenDB use an __index__ to provide results, even when you don't specify one. +* All queries in RavenDB use an **index** to provide results, even when you don't specify one. Learn more [below](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). -* Queries that do Not specify which index to use are called __Dynamic Queries__. +* Queries that do Not specify which index to use are called **Dynamic Queries**. This article displays examples of dynamic queries only. For examples showing how to query an index see [querying an index](../../../indexes/querying/query-index). --- -* The entities returned by the query are 'loaded' and __tracked__ by the [Session](../../../client-api/session/what-is-a-session-and-how-does-it-work). +* The entities returned by the query are 'loaded' and **tracked** by the [Session](../../../client-api/session/what-is-a-session-and-how-does-it-work). Entities will Not be tracked when: * Query returns a [projection](../../../client-api/session/querying/how-to-project-query-results) * Tracking is [disabled](../../../client-api/session/configuration/how-to-disable-tracking#disable-tracking-query-results) -* Query results are __cached__ by default. To disable query caching see [NoCaching](../../../client-api/session/querying/how-to-customize-query#nocaching). +* Query results are **cached** by default. To disable query caching see [NoCaching](../../../client-api/session/querying/how-to-customize-query#nocaching). * Queries are timed out after a configurable time period. See [query timeout](../../../server/configuration/database-configuration#databases.querytimeoutinsec). @@ -52,7 +52,7 @@ * Queries always use an index to provide fast results regardless of the size of your data. -* When a query reaches a RavenDB instance, the instance calls its __query optimizer__ to analyze the query +* When a query reaches a RavenDB instance, the instance calls its **query optimizer** to analyze the query and determine which index should be used to retrieve the requested data. * Indexes allow to provide query results without scanning the entire dataset each and every time. @@ -60,7 +60,7 @@ {INFO: } -We differentiate between the following __3 query scenarios__: +We differentiate between the following **3 query scenarios**: * Index query * Dynamic query @@ -73,12 +73,12 @@ For each scenario, a different index type will be used. {NOTE: } -__1. Query an existing index__: +**1. Query an existing index**: -* __Query type__: Index query - __Index used__: Static-index +* **Query type**: Index query + **Index used**: Static-index -* You can specify which __STATIC-index__ the query will use. +* You can specify which **STATIC-index** the query will use. * Static indexes are defined by the user, as opposed to auto-indexes that are created by the server when querying a collection with some filtering applied. See [Static-index vs Auto-index](../../../studio/database/indexes/indexes-overview#auto-indexes--vs--static-indexes). @@ -92,13 +92,13 @@ __1. Query an existing index__: {NOTE: } -__2. Query a collection - with filtering__: +**2. Query a collection - with filtering**: -* __Query type__: Dynamic Query - __Index used__: Auto-index +* **Query type**: Dynamic Query + **Index used**: Auto-index * When querying a collection without specifying an index and with some filtering condition - (other than just the document ID) the query-optimizer will analyze the query to see if an __AUTO-index__ + (other than just the document ID) the query-optimizer will analyze the query to see if an **AUTO-index** that can answer the query already exists, i.e. an auto-index on the collection queried with index-fields that match those queried. * If such auto-index (Not a static one...) is found, it will be used to fetch the results. @@ -132,17 +132,17 @@ __2. Query a collection - with filtering__: {NOTE: } -__3. Query a collection - query full collection | query by ID__: +**3. Query a collection - query full collection | query by ID**: -* __Query type__: Full collection Query - __Index used__: The raw collection (internal storage indexes) +* **Query type**: Full collection Query + **Index used**: The raw collection (internal storage indexes) * Full collection query: * When querying a collection without specifying an index and with no filtering condition, then all documents from the specified collection are returned. - * RavenDB uses the raw collection documents in its __internal storage indexes__ as the source for this query. + * RavenDB uses the raw collection documents in its **internal storage indexes** as the source for this query. No auto-index is created. * Example RQL:   `from Employees` @@ -166,14 +166,14 @@ __3. Query a collection - query full collection | query by ID__: * The simplest way to issue a query is by using the session's `Query` method which supports LINQ. Both the LINQ method syntax and the LINQ query syntax are supported. -* The following examples show __dynamic queries__ that do not specify which index to use. +* The following examples show **dynamic queries** that do not specify which index to use. Please refer to [querying an index](../../../indexes/querying/query-index) for other examples. * Querying can be enhanced using these [extension methods](../../../client-api/session/querying/how-to-query#custom-methods-and-extensions-for-linq). {NOTE: } -__Query collection - no filtering__ +**Query collection - no filtering** {CODE-TABS} {CODE-TAB:csharp:Method-syntax query_1_1@ClientApi\Session\Querying\HowToQuery.cs /} @@ -192,7 +192,7 @@ from "Employees" {NOTE: } -__Query collection - by ID__ +**Query collection - by ID** {CODE-TABS} {CODE-TAB:csharp:Method-syntax query_2_1@ClientApi\Session\Querying\HowToQuery.cs /} @@ -211,7 +211,7 @@ from "Employees" where id() == "employees/1-A" {NOTE: } -__Query collection - with filtering__ +**Query collection - with filtering** {CODE-TABS} {CODE-TAB:csharp:Method-syntax query_3_1@ClientApi\Session\Querying\HowToQuery.cs /} @@ -232,7 +232,7 @@ from "Employees" where FirstName == "Robert" {NOTE: } -__Query collection - with paging__ +**Query collection - with paging** {CODE-TABS} {CODE-TAB:csharp:Method-syntax query_4_1@ClientApi\Session\Querying\HowToQuery.cs /} @@ -263,7 +263,7 @@ from "Products" limit 5, 10 // skip 5, take 10 * [What is a document query](../../../client-api/session/querying/document-query/what-is-document-query) * [Query -vs- DocumentQuery](../../../client-api/session/querying/document-query/query-vs-document-query) -__Example__: +**Example**: {CODE-TABS} {CODE-TAB:csharp:DocumentQuery query_5_1@ClientApi\Session\Querying\HowToQuery.cs /} @@ -287,7 +287,7 @@ from "Employees" where FirstName = "Robert" * The session also gives you a way to express the query directly in RQL using the `RawQuery` method. -__Example__: +**Example**: {CODE-TABS} {CODE-TAB:csharp:RawQuery query_6_1@ClientApi\Session\Querying\HowToQuery.cs /} @@ -339,12 +339,12 @@ Available custom methods and extensions for the session's [Query](../../../clien | Parameter | Type | Description | |--------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| __T__ | object |
  • The type of entities queried
| -| __TIndexCreator__ | string |
  • The index class type
| -| __collectionName__ | string |
  • Name of a collection to query
  • No need to provide this param when specifying `T`
  • Specify the collection name when querying a collection that is created
    on the fly, i.e. when querying [Artifical Documents](../../../studio/database/indexes/create-map-reduce-index#saving-map-reduce-results-in-a-collection-(artificial-documents))
  • Mutually exclusive with _indexName_
| -| __indexName__ | string |
  • Name of index to query
  • Mutually exclusive with _collectionName_
| -| __isMapReduce__ | string |
  • Whether querying a map-reduce index
| -| __query__ | string |
  • The RQL query string
| +| **T** | object |
  • The type of entities queried
| +| **TIndexCreator** | string |
  • The index class type
| +| **collectionName** | string |
  • Name of a collection to query
  • No need to provide this param when specifying `T`
  • Specify the collection name when querying a collection that is created
    on the fly, i.e. when querying [Artifical Documents](../../../studio/database/indexes/create-map-reduce-index#saving-map-reduce-results-in-a-collection-(artificial-documents))
  • Mutually exclusive with _indexName_
| +| **indexName** | string |
  • Name of index to query
  • Mutually exclusive with _collectionName_
| +| **isMapReduce** | string |
  • Whether querying a map-reduce index
| +| **query** | string |
  • The RQL query string
| | Return Value | | | - | - | diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.js.markdown index 6938aa9ec5..19a5464d4d 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.js.markdown @@ -14,21 +14,21 @@ --- -* All queries in RavenDB use an __index__ to provide results, even when you don't specify one. +* All queries in RavenDB use an **index** to provide results, even when you don't specify one. Learn more [below](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). -* Queries that do Not specify which index to use are called __Dynamic Queries__. +* Queries that do Not specify which index to use are called **Dynamic Queries**. This article displays examples of dynamic queries only. For examples showing how to query an index see [querying an index](../../../indexes/querying/query-index). --- -* The entities returned by the query are 'loaded' and __tracked__ by the [Session](../../../client-api/session/what-is-a-session-and-how-does-it-work). +* The entities returned by the query are 'loaded' and **tracked** by the [Session](../../../client-api/session/what-is-a-session-and-how-does-it-work). Entities will Not be tracked when: * Query returns a [projection](../../../client-api/session/querying/how-to-project-query-results) * Tracking is [disabled](../../../client-api/session/configuration/how-to-disable-tracking#disable-tracking-query-results) -* Query results are __cached__ by default. To disable query caching see [noCaching](../../../client-api/session/querying/how-to-customize-query#nocaching). +* Query results are **cached** by default. To disable query caching see [noCaching](../../../client-api/session/querying/how-to-customize-query#nocaching). * Queries are timed out after a configurable time period. See [query timeout](../../../server/configuration/database-configuration#databases.querytimeoutinsec). @@ -49,7 +49,7 @@ * Queries always use an index to provide fast results regardless of the size of your data. -* When a query reaches a RavenDB instance, the instance calls its __query optimizer__ to analyze the query +* When a query reaches a RavenDB instance, the instance calls its **query optimizer** to analyze the query and determine which index should be used to retrieve the requested data. * Indexes allow to provide query results without scanning the entire dataset each and every time. @@ -57,7 +57,7 @@ {INFO: } -We differentiate between the following __3 query scenarios__: +We differentiate between the following **3 query scenarios**: * Index query * Dynamic query @@ -70,12 +70,12 @@ For each scenario, a different index type will be used. {NOTE: }
-__1. Query an existing index__: +**1. Query an existing index**: -* __Query type__: Index query - __Index used__: Static-index +* **Query type**: Index query + **Index used**: Static-index -* You can specify which __STATIC-static index__ the query will use. +* You can specify which **STATIC-static index** the query will use. * Static indexes are defined by the user, as opposed to auto-indexes that are created by the server when querying a collection with some filtering applied. See [Static-index vs Auto-index](../../../studio/database/indexes/indexes-overview#auto-indexes--vs--static-indexes). @@ -88,13 +88,13 @@ __1. Query an existing index__: {NOTE: } -__2. Query a collection - with filtering (Dynamic Query)__: +**2. Query a collection - with filtering (Dynamic Query)**: -* __Query type__: Dynamic Query - __Index used__: Auto-index +* **Query type**: Dynamic Query + **Index used**: Auto-index * When querying a collection without specifying an index and with some filtering condition - (other than just the document ID) the query-optimizer will analyze the query to see if an __AUTO-index__ + (other than just the document ID) the query-optimizer will analyze the query to see if an **AUTO-index** that can answer the query already exists, i.e. an auto-index on the collection queried with index-fields that match those queried. * If such auto-index (Not a static one...) is found, it will be used to fetch the results. @@ -128,17 +128,17 @@ __2. Query a collection - with filtering (Dynamic Query)__: {NOTE: } -__3. Query a collection - no filtering__: +**3. Query a collection - no filtering**: -* __Query type__: Full collection Query - __Index used__: The raw collection (internal storage indexes) +* **Query type**: Full collection Query + **Index used**: The raw collection (internal storage indexes) * Full collection query: * When querying a collection without specifying an index and with no filtering condition, then all documents from the specified collection are returned. - * RavenDB uses the raw collection documents in its __internal storage indexes__ as the source for this query. + * RavenDB uses the raw collection documents in its **internal storage indexes** as the source for this query. No auto-index is created. * Example RQL:   `from Employees` @@ -162,12 +162,12 @@ __3. Query a collection - no filtering__: * The simplest way to issue a query is by using the session's `query` method. Customize your query with these [API methods](../../../client-api/session/querying/how-to-query#query-api). -* The following examples show __dynamic queries__ that do not specify which index to use. +* The following examples show **dynamic queries** that do not specify which index to use. Please refer to [querying an index](../../../indexes/querying/query-index) for other examples. {NOTE: } -__Query collection - no filtering__ +**Query collection - no filtering** {CODE-TABS} {CODE-TAB:nodejs:Query query_1_0@client-api\session\Querying\howToQuery.js /} @@ -184,7 +184,7 @@ from "employees" {NOTE: } -__Query collection - by ID__ +**Query collection - by ID** {CODE-TABS} {CODE-TAB:nodejs:Query query_2_0@client-api\session\Querying\howToQuery.js /} @@ -201,7 +201,7 @@ from "employees" where id() == "employees/1-A" {NOTE: } -__Query collection - with filtering__ +**Query collection - with filtering** {CODE-TABS} {CODE-TAB:nodejs:Query query_3_0@client-api\session\Querying\howToQuery.js /} @@ -220,7 +220,7 @@ from "employees" where firstName == "Robert" {NOTE: } -__Query collection - with paging__ +**Query collection - with paging** {CODE-TABS} {CODE-TAB:nodejs:Query query_4_0@client-api\session\Querying\howToQuery.js /} @@ -245,7 +245,7 @@ from "products" limit 5, 10 // skip 5, take 10 * The session also gives you a way to express the query directly in RQL using the `rawQuery` method. -__Example__: +**Example**: {CODE:nodejs query_5@client-api\session\Querying\howToQuery.js /} @@ -335,16 +335,16 @@ Available methods for the session's [query](../../../client-api/session/querying | Parameter | Type | Description | |------------------|-------------------------------|------------------------------| -| __documentType__ | object | The type of entities queried | -| __index__ | object | The index class | -| __opts__ | `DocumentQueryOptions` object | Query options | -| __query__ | string | The RQL query string | +| **documentType** | object | The type of entities queried | +| **index** | object | The index class | +| **opts** | `DocumentQueryOptions` object | Query options | +| **query** | string | The RQL query string | | `DocumentQueryOptions` | | | | - | - | - | -| __collection__ | string |
  • Collection name queried
| -| __indexName__ | string |
  • Index name queried
| -| __index__ | object |
  • Index object queried
  • Note:
    `indexName` & `index` are mutually exclusive with `collection`.
    See examples in [querying an index](../../../indexes/querying/query-index).
| +| **collection** | string |
  • Collection name queried
| +| **indexName** | string |
  • Index name queried
| +| **index** | object |
  • Index object queried
  • Note:
    `indexName` & `index` are mutually exclusive with `collection`.
    See examples in [querying an index](../../../indexes/querying/query-index).
| | Return Value | | | - | - | diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.php.markdown new file mode 100644 index 0000000000..8ae1efb9f6 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.php.markdown @@ -0,0 +1,354 @@ +# Query Overview + +--- + +{NOTE: } + +* PHP Queries can be written - + * Using the session `query` method + * Using the session `documentQuery` method + * Using **RQL**: + * via the session `rawQuery` method + * via Studio's [Query view](../../../studio/database/queries/query-view) + +* Queries defined using `query` or `documentQuery` are translated by the RavenDB client + to [RQL](../../../client-api/session/querying/what-is-rql) when sent to the server. + +--- + +* All RavenDB queries use an **index** to provide results, even when an index is not explicitly defined. + Learn more [below](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). + +* Queries that do Not specify which index to use are called **Dynamic Queries**. + This article shows examples of dynamic queries only. + For index query examples see [querying an index](../../../indexes/querying/query-index). + +--- + +* The entities returned by the query are 'loaded' and **tracked** by the [session](../../../client-api/session/what-is-a-session-and-how-does-it-work). + Entities will Not be tracked when: + * Query returns a [projection](../../../client-api/session/querying/how-to-project-query-results) + * Tracking is [disabled](../../../client-api/session/querying/how-to-customize-query#notracking) + +* Query results are **cached** by default. + To disable query caching see [NoCaching](../../../client-api/session/querying/how-to-customize-query#nocaching). + +* Queries are timed out after a configurable time period. + See [query timeout](../../../server/configuration/database-configuration#databases.querytimeoutinsec). + +--- + +* In this page: + * [Queries always provide results using an index](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index) + * [session.query](../../../client-api/session/querying/how-to-query#session.query) + * [session.advanced.documentQuery](../../../client-api/session/querying/how-to-query#session.advanced.documentquery) + * [session.advanced.rawQuery](../../../client-api/session/querying/how-to-query#session.advanced.rawquery) + * [Custom methods](../../../client-api/session/querying/how-to-query#custom-methods) + * [Syntax](../../../client-api/session/querying/how-to-query#syntax) + +{NOTE/} + +--- + +{PANEL: Queries always provide results using an index} + +* Queries always use an index to provide fast results regardless of the size of your data. + +* When a query reaches a RavenDB instance, the instance calls its **query optimizer** to analyze the query + and determine which index should be used to retrieve the requested data. + +* Indexes allow to provide query results without scanning the entire dataset each and every time. + Learn more about indexes in [indexes overview](../../../studio/database/indexes/indexes-overview). + +{INFO: } + +We differentiate between the following **3 query scenarios**: + + * Index query + * Dynamic query + * Full collection query + +For each scenario, a different index type will be used. + +{INFO/} + +{NOTE: } + +
+**1. Query an existing index**: + +* **Query type**: Index query + **Index used**: Static-index + +* You can specify which **STATIC-index** the query will use. + +* Static indexes are defined by the user, as opposed to auto-indexes that are created by the server + when querying a collection with some filtering applied. See [Static-index vs Auto-index](../../../studio/database/indexes/indexes-overview#auto-indexes--vs--static-indexes). + + +* Example RQL:   `from index "Employees/ByFirstName" where FirstName == "Laura"` + See more examples in [querying an index](../../../indexes/querying/query-index). + +{NOTE/} + +{NOTE: } + + +**2. Query a collection - with filtering**: + +* **Query type**: Dynamic Query + **Index used**: Auto-index + +* When querying a collection without specifying an index and with some filtering condition + (other than just the document ID) the query-optimizer will analyze the query to see if an **AUTO-index** + that can answer the query already exists, i.e. an auto-index on the collection queried with index-fields that match those queried. + +* If such auto-index (Not a static one...) is found, it will be used to fetch the results. + +* Else, if no relevant auto-index is found, + the query-optimizer will create a new auto-index with fields that match the query criteria. + At this time, and only at this time, the query will wait for the auto-indexing process to complete. + Subsequent queries that target this auto-index will be served immediately. + +* Note: if there exists an auto-index that is defined on the collection queried + but is indexing a different field than the one queried on, + then the query-optimizer will create a new auto-index that merges both the + fields from the existing auto-index and the new fields queried. + +* Once the newly created auto-index is done indexing the data, + the old auto-index is removed in favor of the new one. + +* Over time, an optimal set of indexes is generated by the query optimizer to answer your queries. + +* RQL Example:   `from Employees where FirstName == "Laura"` + See more examples [below](../../../client-api/session/querying/how-to-query#session.query). + +--- + +* Note: Counters and Time series are an exception to this flow. + Dynamic queries on counters and time series values don't create auto-indexes. + However, a static-index can be defined on [Time series](../../../document-extensions/timeseries/indexing) + and [Counters](../../../document-extensions/counters/indexing). + +{NOTE/} + +{NOTE: } + + +**3. Query a collection - query full collection | query by ID**: + +* **Query type**: Full collection Query + **Index used**: The raw collection (internal storage indexes) + +* Full collection query: + + * When querying a collection without specifying an index and with no filtering condition, + then all documents from the specified collection are returned. + + * RavenDB uses the raw collection documents in its **internal storage indexes** as the source for this query. + No auto-index is created. + + * Example RQL:   `from Employees` + +* Query by document ID: + + * When querying a collection only by document ID or IDs, + then similar to the full collection query, no auto-index is created. + + * RavenDB uses the raw collection documents as the source for this query. + + * Example RQL:   `from Employees where id() == "employees/1-A"` + See more examples [below](../../../client-api/session/querying/how-to-query#session.query). + +{NOTE/} + +{PANEL/} + +{PANEL: session.query} + +* The simplest way to issue a query is by using the session's `query` method which supports LINQ. + Both the LINQ method syntax and the LINQ query syntax are supported. + +* The following examples show **dynamic queries** that do not specify which index to use. + Please refer to [querying an index](../../../indexes/querying/query-index) for other examples. + +* Querying can be enhanced using these [extension methods](../../../client-api/session/querying/how-to-query#custom-methods-and-extensions-for-linq). + +{NOTE: } + +**Query collection - no filtering** + +{CODE-TABS} +{CODE-TAB:php query_1_1@ClientApi\Session\Querying\HowToQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +// This RQL is a Full Collection Query +// No auto-index is created since no filtering is applied + +from "Employees" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{NOTE/} + +{NOTE: } + +**Query collection - by ID** + +{CODE-TABS} +{CODE-TAB:php query_2_1@ClientApi\Session\Querying\HowToQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +// This RQL queries the 'Employees' collection by ID +// No auto-index is created when querying only by ID + +from "Employees" where id() == "employees/1-A" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{NOTE/} + +{NOTE: } + +**Query collection - with filtering** + +{CODE-TABS} +{CODE-TAB:php query_3_1@ClientApi\Session\Querying\HowToQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Query collection - filter by document field + +// An auto-index will be created if there isn't already an existing auto-index +// that indexes the requested field + +from "Employees" where FirstName == "Robert" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{NOTE/} + +{NOTE: } + +**Query collection - with paging** + +{CODE-TABS} +{CODE-TAB:php:Method-syntax query_4_1@ClientApi\Session\Querying\HowToQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Query collection - page results +// No auto-index is created since no filtering is applied + +from "Products" limit 5, 10 // skip 5, take 10 +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +* By default, if the page size is not specified, all matching records will be retrieved from the database. + +{NOTE/} + +{PANEL/} + +{PANEL: session.advanced.documentQuery} + +* `documentQuery` provides a full spectrum of low-level querying capabilities, + giving you more flexibility and control when making complex queries. + +* Below is a simple _DocumentQuery_ usage. + For a full description and more examples see: + * [What is a document query](../../../client-api/session/querying/document-query/what-is-document-query) + * [query -vs- documentQuery](../../../client-api/session/querying/document-query/query-vs-document-query) + +**Example**: + +{CODE-TABS} +{CODE-TAB:php query_5_1@ClientApi\Session\Querying\HowToQuery.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Query collection - filter by document field + +// An auto-index will be created if there isn't already an existing auto-index +// that indexes the requested field + +from "Employees" where FirstName = "Robert" +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: session.advanced.rawQuery} + +* Queries defined with [query](../../../client-api/session/querying/how-to-query#session.query) + or [documentQuery](../../../client-api/session/querying/how-to-query#session.advanced.documentquery) + are translated by the RavenDB client to [RQL](../../../client-api/session/querying/what-is-rql) + when sent to the server. + +* The session also gives you a way to express the query directly in RQL using the `rawQuery` method. + +**Example**: + +{CODE:php query_6_1@ClientApi\Session\Querying\HowToQuery.php /} + +{PANEL/} + +{PANEL: Custom methods} + +Available custom methods for session's [query](../../../client-api/session/querying/how-to-query#session.query) method: + +- [aggregateBy](../../../client-api/session/querying/how-to-perform-a-faceted-search) +- [count](../../../client-api/session/querying/how-to-count-query-results) +- [countLazily](../../../client-api/session/querying/how-to-perform-queries-lazily) +- [customize](../../../client-api/session/querying/how-to-customize-query) +- [highlight](../../../client-api/session/querying/text-search/highlight-query-results) +- [include](../../../client-api/how-to/handle-document-relationships) +- [intersect](../../../client-api/session/querying/how-to-use-intersect) +- [lazily](../../../client-api/session/querying/how-to-perform-queries-lazily) +- [longCount](../../../client-api/session/querying/how-to-count-query-results) +- [moreLikeThis](../../../client-api/session/querying/how-to-use-morelikethis) +- [ofType](../../../client-api/session/querying/how-to-project-query-results#oftype-(as)---simple-projection) +- [orderByDistance](../../../client-api/session/querying/how-to-make-a-spatial-query#orderByDistance) +- [orderByDistanceDescending](../../../client-api/session/querying/how-to-make-a-spatial-query#orderByDistanceDesc) +- [orderByScore](../../../client-api/session/querying/sort-query-results#order-by-score) +- [orderByScoreDescending](../../../client-api/session/querying/sort-query-results#order-by-score) +- [projectInto](../../../client-api/session/querying/how-to-project-query-results) +- [search](../../../client-api/session/querying/text-search/full-text-search) +- [spatial](../../../client-api/session/querying/how-to-make-a-spatial-query) +- [statistics](../../../client-api/session/querying/how-to-get-query-statistics) +- [suggestUsing](../../../client-api/session/querying/how-to-work-with-suggestions) + +{PANEL/} + +{PANEL: Syntax} + +{CODE:php syntax@ClientApi\Session\Querying\HowToQuery.php /} + +| Parameter | Type | Description | +|--------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **$className** | `string` | The name of the class to query | +| **$collectionOrIndexName** | `?string` | The name of the collection or index to query | +| **$indexNameOrClass** | `?string` | The name or class of the index to query | +| **$collectionName** | `?string` | The name of the collection to query | +| **$isMapReduce** | `bool` | Whether querying a map-reduce index | +| **$query** |`string` | The RQL query string | + +| Return Value | | +| - | - | +| `DocumentQueryInterface`
`RawDocumentQueryInterface` | Interfaces exposing additional query methods and [extensions](../../../client-api/session/querying/how-to-query#custom-methods) | + +{PANEL/} + +## Related Articles + +### Session + +- [How to Project Query Results](../../../client-api/session/querying/how-to-project-query-results) +- [How to Stream Query Results](../../../client-api/session/querying/how-to-stream-query-results) +- [What is a Document Query](../../../client-api/session/querying/document-query/what-is-document-query) + +### Querying + +- [Querying an Index](../../../indexes/querying/query-index) +- [Filtering](../../../indexes/querying/filtering) +- [Paging](../../../indexes/querying/paging) +- [Sorting](../../../indexes/querying/sorting) +- [Projections](../../../indexes/querying/projections) + +### Indexes + +- [What are Indexes](../../../indexes/what-are-indexes) +- [Indexing Basics](../../../indexes/indexing-basics) +- [Map Indexes](../../../indexes/map-indexes) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.python.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.python.markdown index fc2cf7813c..49010ba362 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.python.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-query.python.markdown @@ -296,7 +296,7 @@ Available custom methods for session's [query](../../../client-api/session/query - [lazily](../../../client-api/session/querying/how-to-perform-queries-lazily) - [long_count](../../../client-api/session/querying/how-to-count-query-results) - [more_like_this](../../../client-api/session/querying/how-to-use-morelikethis) -- [if_type](../../../client-api/session/querying/how-to-project-query-results#oftype-(as)---simple-projection) +- [of_type](../../../client-api/session/querying/how-to-project-query-results#oftype-(as)---simple-projection) - [order_by_distance](../../../client-api/session/querying/how-to-make-a-spatial-query#orderByDistance) - [order_by_distance_descending](../../../client-api/session/querying/how-to-make-a-spatial-query#orderByDistanceDesc) - [order_by_score](../../../client-api/session/querying/sort-query-results#order-by-score) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-intersect.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-intersect.php.markdown new file mode 100644 index 0000000000..c52ec22260 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-intersect.php.markdown @@ -0,0 +1,28 @@ +# Using Intersect + +To return only documents that match **all** provided sub-queries, use the +`intersect` extension to allow RavenDB to perform server-side intersection queries. + +## Syntax + +{CODE:php intersect_1@ClientApi\Session\Querying\HowToUseIntersect.php /} + +## Example + +{CODE-TABS} +{CODE-TAB:php:Sync intersect_2@ClientApi\Session\Querying\HowToUseIntersect.php /} +{CODE-TAB-BLOCK:sql:RQL} +from index 'TShirts/ByManufacturerColorSizeAndReleaseYear' +where intersect(Manufacturer = 'Raven', Color = 'Blue' and Size = 'Small', Color = 'Gray' and Size = 'Large') +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +## Related articles + +### Session + +- [How to Query](../../../client-api/session/querying/how-to-query) + +### Querying + +- [Intersection](../../../indexes/querying/intersection) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-morelikethis.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-morelikethis.php.markdown new file mode 100644 index 0000000000..079640c20a --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-use-morelikethis.php.markdown @@ -0,0 +1,71 @@ +# Using   `moreLikeThis` + +`moreLikeThis` is available through query extension methods and will return similar documents according to the provided criteria and options. + +## Syntax + +{CODE:php more_like_this_1@ClientApi\Session\Querying\MoreLikeThis.php /} + +| Parameters | | | +| ------------- | ------------- | ----- | +| **$moreLikeThisOrBuilder** | `null`
`MoreLikeThisBase`
`Closure` | Defines the type of MoreLikeThis that should be executed | + +### Builder + +{CODE:php more_like_this_3@ClientApi\Session\Querying\MoreLikeThis.php /} + +| Parameters | | | +| ------------- | ------------- | ----- | +| **$documentJsonOrBuilder** | `null`
`string`
`Closure` | Builder or Inline JSON document to be used as a base for the operation | +| **$documentJson** | ?string | Inline JSON document to be used as a base for the operation | +| **$builder** | `?Closure` | Builder with fluent API that constructs the `MoreLikeThisOperationsInterface` instance | +| **$options** | `MoreLikeThisOptions` | Available operation options (see below) | + +### Options + +{CODE:php more_like_this_2@ClientApi\Session\Querying\MoreLikeThis.php /} + +| Options | | | +| ------------- | ------------- | ----- | +| **$minimumTermFrequency** | `?int` | Ignores terms with less than this frequency in the source doc | +| **$maximumQueryTerms** | `?int` | Returns a query with no more than this many terms | +| **$maximumNumberOfTokensParsed** | `?int` | The maximum number of tokens to parse in each example doc field that is not stored with TermVector support | +| **$minimumWordLength** | `?int` | Ignores words less than this length or, if 0, then this has no effect | +| **$maximumWordLength** | `?int` | Ignores words greater than this length or if 0 then this has no effect | +| **$minimumDocumentFrequency** | `?int` | Ignores words which do not occur in at least this many documents | +| **$maximumDocumentFrequency** | `?int` | Ignores words which occur in more than this many documents | +| **$maximumDocumentFrequencyPercentage** | `int?` | Ignores words which occur in more than this percentage of documents | +| **$boost** | `?bool` | Boost terms in query based on score | +| **$boostFactor** | `?float` | Boost factor when boosting based on score | +| **$stopWordsDocumentId** | `?string` | Document ID containing custom stop words | +| **$fields** | `?array` | Fields to compare | + +## Example I + +{CODE-TABS} +{CODE-TAB:php:Sync more_like_this_4@ClientApi\Session\Querying\MoreLikeThis.php /} +{CODE-TAB-BLOCK:sql:RQL} +from index 'Articles/MoreLikeThis' +where morelikethis(id() = 'articles/1', '{ "Fields" : [ "Body" ] }') +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +## Example II + +{CODE-TABS} +{CODE-TAB:php:Sync more_like_this_6@ClientApi\Session\Querying\MoreLikeThis.php /} +{CODE-TAB-BLOCK:sql:RQL} +from index 'Articles/MoreLikeThis' +where morelikethis(id() = 'articles/1', '{ "Fields" : [ "Body" ] }') and Category == 'IT' +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +## Related Articles + +### Session + +- [How to Query](../../../client-api/session/querying/how-to-query) + +### Querying + +- [MoreLikeThis](../../../indexes/querying/morelikethis) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.dotnet.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.dotnet.markdown index 9772405fdf..c071b415d6 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.dotnet.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.dotnet.markdown @@ -4,12 +4,12 @@ {NOTE: } -* Given a string term, the Suggestion feature will offer __similar terms__ from your data. +* Given a string term, the Suggestion feature will offer **similar terms** from your data. * Word similarities are found using string distance algorithms. -* Examples in this article demonstrate getting suggestions with a __dynamic-query__. - For getting suggestions with an __index-query__ see [query for suggestions with index](../../../indexes/querying/suggestions). +* Examples in this article demonstrate getting suggestions with a **dynamic-query**. + For getting suggestions with an **index-query** see [query for suggestions with index](../../../indexes/querying/suggestions). --- @@ -36,7 +36,7 @@ * All queries in RavenDB use an index - learn more about that [here](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). Whether making a dynamic query which generates an auto-index or using a static index, - the data from your documents is 'broken' into __terms__ that are kept in the index. + the data from your documents is 'broken' into **terms** that are kept in the index. * This tokenization process (what terms will be generated) depends on the analyzer used, various analyzers differ in the way they split the text stream. Learn more in [Analyzers](../../../indexes/using-analyzers). @@ -49,7 +49,7 @@ Querying for suggestions is useful in the following scenarios: - * __When query has no results__: + * **When query has no results**: * When searching for documents that match some condition on a given string term, if the term is misspelled then you will Not get any results. @@ -58,7 +58,7 @@ Querying for suggestions is useful in the following scenarios: * The suggested terms can then be used in a new query to retrieve matching documents, or simply presented to the user asking what they meant to query. - * __When looking for alternative terms__: + * **When looking for alternative terms**: * When simply searching for additional alternative terms for a term that does exist. @@ -84,7 +84,7 @@ as no document in the Products collection contains the term `chaig` in its `Name The generated terms are visible in the Studio - see image [below](../../../client-api/session/querying/how-to-work-with-suggestions#the-auto-index-terms-in-studio). * If you suspect that the term `chaig` in the query criteria is written incorrectly, - you can ask RavenDB to suggest __existing terms__ that are similar to `chaig`, as follows:. + you can ask RavenDB to suggest **existing terms** that are similar to `chaig`, as follows:. {CODE-TABS} {CODE-TAB:csharp:Query suggest_2@ClientApi\Session\Querying\HowToWorkWithSuggestions.cs /} @@ -166,47 +166,47 @@ Based on the Northwind sample data, these are the terms generated for index `Aut ![Figure 1. Auto-index terms](images/auto-index-terms.png "Terms generated for index Auto/Products/ByName") -1. __The field name__ - derived from the document field that was used in the dynamic-query. +1. **The field name** - derived from the document field that was used in the dynamic-query. In this example the field name is `Name`. -2. __The terms__ generated from the data that the Products collection documents have in their `Name` field. +2. **The terms** generated from the data that the Products collection documents have in their `Name` field. {PANEL/} {PANEL: Syntax} -__Suggest using__: +**Suggest using**: {CODE syntax_1@ClientApi\Session\Querying\HowToWorkWithSuggestions.cs /} | Parameter | Type | Description | |----------------|----------------------------------------------|-------------------------------------------------------------------------------| -| __suggestion__ | `SuggestionWithTerm` / `SuggestionWithTerms` | An instance of `SuggestionBase`.
Defines the type of suggestion requested. | -| __builder__ | `Action>` | Builder with a fluent API that constructs a `SuggestionBase` instance. | +| **suggestion** | `SuggestionWithTerm` / `SuggestionWithTerms` | An instance of `SuggestionBase`.
Defines the type of suggestion requested. | +| **builder** | `Action>` | Builder with a fluent API that constructs a `SuggestionBase` instance. | -__Builder operations__: +**Builder operations**: {CODE syntax_2@ClientApi\Session\Querying\HowToWorkWithSuggestions.cs /} | Parameter | Type | Description | |-----------------|-------------------------------|---------------------------------------------------------| -| __fieldName__ | `string` | The index field in which to search for similar terms | -| __path__ | `Expression>` | The index field in which to search for similar terms | -| __term__ | `string` | The term for which to get suggested similar terms | -| __terms__ | `string[]` | List of terms for which to get suggested similar terms | -| __displayName__ | `string` | A custom name for the suggestions result (optional). | -| __options__ | `SuggestionOptions` | Non-default options to use in the operation (optional). | +| **fieldName** | `string` | The index field in which to search for similar terms | +| **path** | `Expression>` | The index field in which to search for similar terms | +| **term** | `string` | The term for which to get suggested similar terms | +| **terms** | `string[]` | List of terms for which to get suggested similar terms | +| **displayName** | `string` | A custom name for the suggestions result (optional). | +| **options** | `SuggestionOptions` | Non-default options to use in the operation (optional). | -__Suggestions options__: +**Suggestions options**: {CODE syntax_3@ClientApi\Session\Querying\HowToWorkWithSuggestions.cs /} | Option | Type | Description | |--------------|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| -| __PageSize__ | `int` |
  • Maximum number of suggested terms that will be returned
  • Default is 15
| -| __Distance__ | `StringDistanceTypes` |
  • String distance algorithm to use
  • `None` / `Levenshtein` / `JaroWinkler` / `NGram`
  • Default is Levenshtein
| -| __Accuracy__ | `float?` |
  • Suggestion accuracy
  • Default is 0.5f
| -| __SortMode__ | `SuggestionSortMode` |
  • Indicates the order by which results are returned
  • `None` / `Popularity`
  • Default is Popularity
| +| **PageSize** | `int` |
  • Maximum number of suggested terms that will be returned
  • Default is 15
| +| **Distance** | `StringDistanceTypes` |
  • String distance algorithm to use
  • `None` / `Levenshtein` / `JaroWinkler` / `NGram`
  • Default is Levenshtein
| +| **Accuracy** | `float?` |
  • Suggestion accuracy
  • Default is 0.5f
| +| **SortMode** | `SuggestionSortMode` |
  • Indicates the order by which results are returned
  • `None` / `Popularity`
  • Default is Popularity
| {PANEL/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.js.markdown index 4b66efec8a..aace911fba 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.js.markdown @@ -4,12 +4,12 @@ {NOTE: } -* Given a string term, the Suggestion feature will offer __similar terms__ from your data. +* Given a string term, the Suggestion feature will offer **similar terms** from your data. * Word similarities are found using string distance algorithms. -* Examples in this article demonstrate getting suggestions with a __dynamic-query__. - For getting suggestions with an __index-query__ see [query for suggestions with index](../../../indexes/querying/suggestions). +* Examples in this article demonstrate getting suggestions with a **dynamic-query**. + For getting suggestions with an **index-query** see [query for suggestions with index](../../../indexes/querying/suggestions). --- @@ -36,7 +36,7 @@ * All queries in RavenDB use an index - learn more about that [here](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). Whether making a dynamic query which generates an auto-index or using a static index, - the data from your documents is 'broken' into __terms__ that are kept in the index. + the data from your documents is 'broken' into **terms** that are kept in the index. * This tokenization process (what terms will be generated) depends on the analyzer used, various analyzers differ in the way they split the text stream. Learn more in [Analyzers](../../../indexes/using-analyzers). @@ -49,7 +49,7 @@ Querying for suggestions is useful in the following scenarios: - * __When query has no results__: + * **When query has no results**: * When searching for documents that match some condition on a given string term, if the term is misspelled then you will Not get any results. @@ -58,7 +58,7 @@ Querying for suggestions is useful in the following scenarios: * The suggested terms can then be used in a new query to retrieve matching documents, or simply presented to the user asking what they meant to query. - * __When looking for alternative terms__: + * **When looking for alternative terms**: * When simply searching for additional alternative terms for a term that does exist. @@ -74,7 +74,7 @@ they will only contain the similar terms. {PANEL: Suggest terms - for single term} Consider this example: -Based on the __Northwind sample data__, the following query has no resulting documents, +Based on the **Northwind sample data**, the following query has no resulting documents, as no document in the Products collection contains the term `chaig` in its `Name` field. {CODE:nodejs suggest_1@client-api\session\Querying\workWithSuggestions.js /} @@ -84,7 +84,7 @@ as no document in the Products collection contains the term `chaig` in its `Name The generated terms are visible in the Studio - see image [below](../../../client-api/session/querying/how-to-work-with-suggestions#the-auto-index-terms-in-studio). * If you suspect that the term `chaig` in the query criteria is written incorrectly, - you can ask RavenDB to suggest __existing terms__ that are similar to `chaig`, as follows:. + you can ask RavenDB to suggest **existing terms** that are similar to `chaig`, as follows:. {CODE-TABS} {CODE-TAB:nodejs:Query suggest_2@client-api\session\Querying\workWithSuggestions.js /} @@ -154,43 +154,43 @@ Based on the Northwind sample data, these are the terms generated for index `Aut ![Figure 1. Auto-index terms](images/auto-index-terms.png "Terms generated for index Auto/Products/ByName") -1. __The field name__ - derived from the document field that was used in the dynamic-query. +1. **The field name** - derived from the document field that was used in the dynamic-query. In this example the field name is `Name`. -2. __The terms__ generated from the data that the Products collection documents have in their `Name` field. +2. **The terms** generated from the data that the Products collection documents have in their `Name` field. {PANEL/} {PANEL: Syntax} -__Suggest using__: +**Suggest using**: {CODE:nodejs syntax_1@client-api\session\Querying\workWithSuggestions.js /} | Parameter | Type | Description | |-------------|---------------------|---------------------------------------------------------------------------------| -| __action__ | `(builder) => void` | Builder function with a fluent API that constructs a `SuggestionBase` instance. | +| **action** | `(builder) => void` | Builder function with a fluent API that constructs a `SuggestionBase` instance. | -__Builder operations__: +**Builder operations**: {CODE:nodejs syntax_2@client-api\session\Querying\workWithSuggestions.js /} | Parameter | Type | Description | |-----------------|------------|----------------------------------------------------------------------------------------------------| -| __fieldName__ | `string` | The index field in which to search for similar terms | -| __term__ | `string` | The term for which to get suggested similar terms | -| __terms__ | `string[]` | List of terms for which to get suggested similar terms | -| __displayName__ | `string` | A custom name for the suggestions result (optional). | -| __options__ | `object` | Non-default suggestion options to use in the operation (optional).
See available options below. | +| **fieldName** | `string` | The index field in which to search for similar terms | +| **term** | `string` | The term for which to get suggested similar terms | +| **terms** | `string[]` | List of terms for which to get suggested similar terms | +| **displayName** | `string` | A custom name for the suggestions result (optional). | +| **options** | `object` | Non-default suggestion options to use in the operation (optional).
See available options below. | -__Suggestions options__: +**Suggestions options**: | Option | Type | Description | |--------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| -| __pageSize__ | `number` |
  • Maximum number of suggested terms that will be returned
  • Default is 15
| -| __distance__ | `string` |
  • String distance algorithm to use
  • `None` / `Levenshtein` / `JaroWinkler` / `NGram`
  • Default is Levenshtein
| -| __accuracy__ | `number ` |
  • Suggestion accuracy
  • Default is 0.5
| -| __sortMode__ | `string` |
  • Indicates the order by which results are returned
  • `None` / `Popularity`
  • Default is Popularity
| +| **pageSize** | `number` |
  • Maximum number of suggested terms that will be returned
  • Default is 15
| +| **distance** | `string` |
  • String distance algorithm to use
  • `None` / `Levenshtein` / `JaroWinkler` / `NGram`
  • Default is Levenshtein
| +| **accuracy** | `number ` |
  • Suggestion accuracy
  • Default is 0.5
| +| **sortMode** | `string` |
  • Indicates the order by which results are returned
  • `None` / `Popularity`
  • Default is Popularity
| {PANEL/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.php.markdown new file mode 100644 index 0000000000..24c9fd6e60 --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/how-to-work-with-suggestions.php.markdown @@ -0,0 +1,168 @@ +# Query for Suggestions + +--- + +{NOTE: } + +* Given a string term, the Suggestion feature will offer **similar terms** from your data. + +* Word similarities are found using string distance algorithms. + +* Examples in this article demonstrate getting suggestions with a **dynamic-query**. + For getting suggestions with an **index-query** see [query for suggestions with index](../../../indexes/querying/suggestions). + +--- + +* In this page: + + * Overview: + * [What are terms](../../../client-api/session/querying/how-to-work-with-suggestions#what-are-terms) + * [When to use suggestions](../../../client-api/session/querying/how-to-work-with-suggestions#when-to-use-suggestions) + + * Examples: + * [Suggest terms - for a single term](../../../client-api/session/querying/how-to-work-with-suggestions#suggest-terms---for-a-single-term) + * [Suggest terms - for multiple terms](../../../client-api/session/querying/how-to-work-with-suggestions#suggest-terms---for-multiple-terms) + + * [The auto-index terms in Studio](../../../client-api/session/querying/how-to-work-with-suggestions#the-auto-index-terms-in-studio) + * [Syntax](../../../client-api/session/querying/how-to-work-with-suggestions#syntax) + +{NOTE/} + +--- + +{PANEL: What are terms} + +* All queries in RavenDB use an index - learn more about that [here](../../../client-api/session/querying/how-to-query#queries-always-provide-results-using-an-index). + Whether making a dynamic query which generates an auto-index or using a static index, + the data from your documents is 'broken' into **terms** that are kept in the index. + +* This tokenization process (what terms will be generated) depends on the analyzer used, + various analyzers differ in the way they split the text stream. Learn more in [Analyzers](../../../indexes/using-analyzers). + +* The terms can then be queried to retrieve matching documents that contain them. + +{PANEL/} + +{PANEL: When to use suggestions} + +Querying for suggestions is useful in the following scenarios: + + * **When query has no results**: + + * When searching for documents that match some condition on a given string term, + if the term is misspelled then you will Not get any results. + You can then ask RavenDB to suggest similar terms that do exist in the index. + + * The suggested terms can then be used in a new query to retrieve matching documents, + or simply presented to the user asking what they meant to query. + + * **When looking for alternative terms**: + + * When simply searching for additional alternative terms for a term that does exist. + +{WARNING: } + +The resulting suggested terms will Not include the term for which you search, +they will only contain the similar terms. + +{WARNING/} + +{PANEL/} + +{PANEL: Suggest terms - for a single term} + +Consider this example: +Based on the Northwind sample data, the following query has no resulting documents, +as no document in the Products collection contains the term `chaig` in its `Name` field. + +{CODE:php suggest_1@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} + +* Executing the above query will generate the auto-index `Auto/Products/ByName`. + This auto-index will contain a list of all available terms from the document field `Name`. + The generated terms are visible in the Studio - see image [below](../../../client-api/session/querying/how-to-work-with-suggestions#the-auto-index-terms-in-studio). + +* If you suspect that the term `chaig` in the query criteria is written incorrectly, + you can ask RavenDB to suggest **existing terms** that are similar to `chaig`, as follows:. + +{CODE-TABS} +{CODE-TAB:php:Query suggest_2@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} +{CODE-TAB:php:DocumentQuery suggest_5@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Query for terms from field 'Name' that are similar to 'chaig' +from "Products" +select suggest(Name, "chaig") +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Suggest terms - for multiple terms} + +{CODE-TABS} +{CODE-TAB:php:Query suggest_7@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} +{CODE-TAB:php:Query_async suggest_8@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} +{CODE-TAB-BLOCK:sql:RQL} +// Query for terms from field 'Name' that are similar to 'chaig' OR 'tof' +from "Products" select suggest(Name, $p0) +{ "p0" : ["chaig", "tof"] } +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: The auto-index terms in Studio} + +Based on the Northwind sample data, these are the terms generated for index `Auto/Products/ByName`: + +![Figure 1. Auto-index terms](images/auto-index-terms.png "Terms generated for index Auto/Products/ByName") + +1. **The field name** - derived from the document field that was used in the dynamic-query. + In this example the field name is `Name`. + +2. **The terms** generated from the data that the Products collection documents have in their `Name` field. + +{PANEL/} + +{PANEL: Syntax} + +**Suggest using**: + +{CODE:php suggest_1@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} + +| Parameter | Type | Description | +|----------------|----------------------------------------------|-------------------------------------------------------------| +| **$suggestionOrBuilder** | `SuggestionBase` | An instance of `SuggestionBase`.
Defines the type of suggestion requested. | +| **$suggestionOrBuilder** | `Closure` | Builder with a fluent API that constructs a `SuggestionBase` instance. | + +**Builder operations**: + +{CODE:php suggest_2@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} + +| Parameter | Type | Description | +|-----------------|---------------------------------|------------------------------------------------------| +| **$fieldName** | `?string` | The index field in which to search for similar terms | +| **$terms** | `null`
`string`
`StringArray`
`array` | List of terms to get suggested similar terms for | +| **$options** | `?SuggestionOptions` | Non-default options to use in the operation (optional) | + +**Suggestions options**: + +{CODE:php suggest_2@ClientApi\Session\Querying\HowToWorkWithSuggestions.php /} + +| Option | Type | Description | +|--------------|-------------------------|---------------------------------------------| +| **$pageSize** | `int` | Maximum number of suggested terms to return | +| **$distance** | `?StringDistanceTypes` | String distance algorithm to use | +| **$accuracy** | `float` | Suggestion accuracy | +| **$sortMode** | `?SuggestionSortMode` | Order to return results by | + +{PANEL/} + +## Related Articles + +### Session + +- [How to Query](../../../client-api/session/querying/how-to-query) + +### Indexes + +- [Query for suggestions with index](../../../indexes/querying/suggestions) diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.js.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.js.markdown index 4ad1a4513d..4465b34963 100644 --- a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.js.markdown +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.js.markdown @@ -4,7 +4,7 @@ {NOTE: } -* When making a query, the server will return the results __sorted__ only if explicitly requested by the query. +* When making a query, the server will return the results **sorted** only if explicitly requested by the query. If no sorting method is specified when issuing the query then results will not be sorted. * Note: An exception to the above rule is when [Boosting](../../../indexes/boosting) is involved in the query. @@ -16,8 +16,8 @@ * Multiple sorting actions can be chained. -* This article provides examples of sorting query results when making a __dynamic-query__. - For sorting results when querying a __static-index__ see [sort index query results](../../../indexes/querying/sorting). +* This article provides examples of sorting query results when making a **dynamic-query**. + For sorting results when querying a **static-index** see [sort index query results](../../../indexes/querying/sorting). * In this page: * [Order by field value](../../../client-api/session/querying/sort-query-results#order-by-field-value) @@ -60,7 +60,7 @@ order by UnitsInStock as long {INFO: } -__Ordering Type__: +**Ordering Type**: * If no ordering type is specified in the query then the server will apply the default lexicographical ordering. @@ -98,12 +98,12 @@ order by score() The score details can be retrieved by either: -* __Request to include explanations__: +* **Request to include explanations**: You can get the score details and see how it was calculated by requesting to include explanations in the query. Currently, this is only available when using Lucene as the underlying indexing engine. Learn more in [Include query explanations](../../../client-api/session/querying/debugging/include-explanations). -* __Get score from metadata__: +* **Get score from metadata**: The score is available in the `@index-score` metadata property within each result. The following example shows how to get the score from the metadata of the resulting entities that were loaded to the session: @@ -187,7 +187,7 @@ select key() as 'Category', sum(UnitsInStock) as sum {NOTE: } -__Using alphanumeric ordering example__: +**Using alphanumeric ordering example**: * When ordering mixed-character strings by the default lexicographical ordering then comparison is done character by character based on the Unicode values. @@ -256,9 +256,9 @@ order by custom(UnitsInStock, "MySorter") | Parameter | Type | Description | |--------------|----------|------------------------------------------------------------------------------------------------------------------------| -| __field__ | `string` | The name of the field to sort by | -| __ordering__ | `string` | The ordering type that will be used to sort the results:
`Long`
`Double`
`AlphaNumeric`
`String` (default) | -| __options__ | `object` | An object that specifies the custom `sorterName` | +| **field** | `string` | The name of the field to sort by | +| **ordering** | `string` | The ordering type that will be used to sort the results:
`Long`
`Double`
`AlphaNumeric`
`String` (default) | +| **options** | `object` | An object that specifies the custom `sorterName` | {PANEL/} diff --git a/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown new file mode 100644 index 0000000000..75bd9b912e --- /dev/null +++ b/Documentation/5.4/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown @@ -0,0 +1,290 @@ +# Sort Query Results + +--- + +{NOTE: } + +* When making a query, the server will return the results **sorted** only if explicitly requested by the query. + If no sorting method is specified when issuing the query then results will not be sorted. + + * Note: An exception to the above rule is when [Boosting](../../../indexes/boosting) is involved in the query. + Learn more in [Automatic score-based ordering](../../../indexes/boosting#automatic-score-based-ordering). + +* Sorting is applied by the server after the query filtering stage. + Applying filtering is recommended as it reduces the number of results RavenDB needs to sort + when querying a large dataset. + +* Multiple sorting actions can be chained. + +* This article provides examples of sorting query results when making a **dynamic-query**. + For sorting results when querying a **static-index** see [sort index query results](../../../indexes/querying/sorting). + +* In this page: + * [Order by field value](../../../client-api/session/querying/sort-query-results#order-by-field-value) + + * [Order by score](../../../client-api/session/querying/sort-query-results#order-by-score) + * [Get resulting score](../../../client-api/session/querying/sort-query-results#get-resulting-score) + + * [Order by random](../../../client-api/session/querying/sort-query-results#order-by-random) + + * [Order by spatial](../../../client-api/session/querying/sort-query-results#order-by-spatial) + + * [Order by count (aggregation query)](../../../client-api/session/querying/sort-query-results#order-by-count-(aggregation-query)) + + * [Order by sum (aggregation query)](../../../client-api/session/querying/sort-query-results#order-by-sum-(aggregation-query)) + + * [Force ordering type](../../../client-api/session/querying/sort-query-results#force-ordering-type) + + * [Chain ordering](../../../client-api/session/querying/sort-query-results#chain-ordering) + + * [Custom sorters](../../../client-api/session/querying/sort-query-results#custom-sorters) + + * [Syntax](../../../client-api/session/querying/sort-query-results#syntax) + +{NOTE/} + +--- + +{PANEL: Order by field value} + +* Use `orderBy` or `orderByDescending` (see below) to order the results by the specified document field. + +{CODE-TABS} +{CODE-TAB:php:Query sort_1@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_3@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by UnitsInStock as long +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{INFO: } + +**Ordering Type**: + +* By default, the `orderBy` methods will determine the `OrderingType` from the property path expression + and specify that ordering type in the generated RQL that is sent to the server. + +* E.g. in the above example, ordering by `UnitsInStock` will result in `OrderingType::long` + because this property's data type is integer. + +* Different ordering can be forced - see [Force ordering type](../../../client-api/session/querying/sort-query-results#force-ordering-type) below. + +{INFO/} + +{PANEL/} + +{PANEL: Order by score} + +* When querying with some filtering conditions, a basic score is calculated for each item in the results + by the underlying indexing engine. (Read more about Lucene scoring [here](https://lucene.apache.org/core/3_3_0/scoring.html)). + +* The higher the score value the better the match. + +* Use `orderByScore` to order the query results by this score. + +{CODE-TABS} +{CODE-TAB:php:Query sort_4@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_6@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock < 5 or Discontinued == true +order by score() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{INFO: } + +#### Get resulting score: + +--- + +The score details can be retrieved by either: + + * **Request to include explanations**: + You can get the score details and see how it was calculated by requesting to include explanations in the query. + Currently, this is only available when using Lucene as the underlying indexing engine. + Learn more in [Include query explanations](../../../client-api/session/querying/debugging/include-explanations). + + * **Get score from metadata**: + The score is available in the `INDEX_SCORE` metadata property within each result. + The following example shows how to get the score from the metadata of the resulting entities that were loaded to the session: + + {CODE:php get_score_from_metadata@ClientApi\Session\Querying\SortQueryResults.php /} + +{INFO/} + +{PANEL/} + +{PANEL: Order by random} + +* Use `randomOrdering` to randomize the order of the query results. + +* An optional seed parameter can be passed. + +{CODE-TABS} +{CODE-TAB:php:Query sort_7@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_9@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by random() +// order by random(someSeed) +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Order by spatial} + +* If your data contains geographical locations, + spatial query results can be sorted based on their distance from a specific point. + +* See detailed explanation in [Spatial Sorting](../../../client-api/session/querying/how-to-make-a-spatial-query#spatial-sorting). + +{PANEL/} + +{PANEL: Order by count (aggregation query)} + +* The results of a [group-by query](../../../client-api/session/querying/how-to-perform-group-by-query) can be sorted by the `Count` aggregation operation used in the query. + +{CODE-TABS} +{CODE-TAB:php:Query sort_10@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_12@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +group by Category +order by count() as long +select key() as "Category", count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Order by sum (aggregation query)} + +* The results of a [group-by query](../../../client-api/session/querying/how-to-perform-group-by-query) can be sorted by the `Sum` aggregation operation used in the query. + +{CODE-TABS} +{CODE-TAB:php:Query sort_13@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_15@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +group by Category +order by Sum as long +select key() as 'Category', sum(UnitsInStock) as Sum +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Force ordering type} + +* By default, the `orderBy` methods will determine the `OrderingType` from the property path expression + and specify that ordering type in the generated RQL that is sent to the server. + +* A different ordering can be forced by passing the ordering type explicitly to `orderBy` or `orderByDescending`. + +* The following ordering types are available: + + * `OrderingType::long` + * `OrderingType::double` + * `OrderingType::alphaNumeric` + * `OrderingType::string` (lexicographic ordering) + +* When using RQL directly, if no ordering type is specified, then the server defaults to lexicographic ordering. + +{NOTE: } + +**Using alphanumeric ordering example**: + +* When ordering mixed-character strings by the default lexicographical ordering + then comparison is done character by character based on the Unicode values. + For example, "Abc9" will come after "Abc10" since 9 is greater than 1. + +* If you want the digit characters to be ordered as numbers then use alphanumeric ordering + where "Abc10" will result after "Abc9". + +{CODE-TABS} +{CODE-TAB:php:Query sort_16@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_18@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +order by QuantityPerUnit as alphanumeric +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{NOTE/} + +{PANEL/} + +{PANEL: Chain ordering} + +* It is possible to chain multiple orderings in the query. + Any combination of secondary sorting is possible as the fields are indexed independently of one another. + +* There is no limit on the number of sorting actions that can be chained. + +{CODE-TABS} +{CODE-TAB:php:Query sort_19@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_21@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by UnitsInStock as long desc, score(), Name +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Custom sorters } + +* The Lucene indexing engine allows you to create your own custom sorters. + Custom sorters can be deployed to the server by either: + + * Sending the [Put Sorters Operation](../../../client-api/operations/maintenance/sorters/put-sorter) from your code. + + * Uploading a custom sorter from Studio, see [Custom Sorters View](../../../studio/database/settings/custom-sorters). + +* Once the custom sorter is deployed, you can sort the query results with it. + +{CODE-TABS} +{CODE-TAB:php:Query sort_22@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_24@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by custom(UnitsInStock, "MySorter") +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Syntax} + +{code:php syntax@ClientApi\Session\Querying\SortQueryResults.php /} + +| Parameter | Type | Description | +|------------|----------|----------------------| +| **$field** | `string` | The field to sort by | +| **$sorterNameOrOrdering** | `string` | The ordering type to sort the results by:
`OrderingType::long`
`OrderingType::double`
`OrderingType::alphaNumeric`
`OrderingType::string` (default) | + +{PANEL/} + +## Related Articles + +#### Client API + +- [Query Overview](../../../client-api/session/querying/how-to-query) + +### Querying + +- [Customize query](../../../client-api/session/querying/how-to-customize-query) +- [Group by query](../../../client-api/session/querying/how-to-perform-group-by-query) +- [Spatial query](../../../client-api/session/querying/how-to-make-a-spatial-query) +- [Full-text search](../../../client-api/session/querying/text-search/full-text-search) + +### Indexes + +- [Sort index query results](../../../indexes/querying/sorting) diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/CountQueryResults.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/CountQueryResults.php new file mode 100644 index 0000000000..9ec37c5f0c --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/CountQueryResults.php @@ -0,0 +1,32 @@ +openSession(); + try { + # region count_3 + /** @var int $numberOfOrders */ + $numberOfOrders = $session->advanced() + ->documentQuery(Order::class) + ->whereEquals("ship_to.country", "UK") + // Calling 'Count' from Raven.Client.Documents.Session + ->Count(); + + // The query returns the NUMBER of orders shipped to UK (int) + # endregion + + } finally { + $session->close(); + } + + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/QueryVsDocumentQuery.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/QueryVsDocumentQuery.php new file mode 100644 index 0000000000..6d9fb92a3b --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/QueryVsDocumentQuery.php @@ -0,0 +1,64 @@ +openSession(); + try { + # region query_1a + $session->query(Order::class) + # endregion + ; + + # region query_1b + $session->advanced()->documentQuery(Order::class) + # endregion + ; + + # region query_2a + $session->query(Order::class, Orders_ByShipToAndLines::class) + # endregion + ; + + # region query_2b + $session->advanced()->documentQuery(Order::class, Orders_ByShipToAndLines::class) + # endregion + ; + + # region query_3a + $session->query(Order::class, Query::index("Orders/ByShipToAndLines")) + # endregion + ; + + # region query_3b + $session->advanced()->documentQuery(Order::class, "Orders/ByShipToAndLines", null, false); + # endregion + + # region query_4a + $session->query(Order::class, Query::collection("orders")) + # endregion + ; + + # region query_4b + $session->advanced()->documentQuery(Order::class, null, "orders", false); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/WhatIsDocumentQuery.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/WhatIsDocumentQuery.php new file mode 100644 index 0000000000..94b37307f2 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/DocumentQuery/WhatIsDocumentQuery.php @@ -0,0 +1,78 @@ +openSession(); + try { + # region documentQuery_2 + // load all entities from 'Employees' collection + $employees = $session + ->advanced() + ->documentQuery(Employee::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region documentQuery_3 + // load all entities from 'Employees' collection + // where firstName equals 'Robert' + $employees = $session + ->advanced() + ->documentQuery(Employee::class) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + + $session = $store->openSession(); + try { + # region documentQuery_4 + // load all entities from 'Employees' collection + // where firstName equals 'Robert' + // using 'My/Custom/Index' + $employees = $session + ->advanced() + ->documentQuery(Employee::class, "My/Custom/Index", null, false) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region documentQuery_5 + // load all entities from 'Employees' collection + // where firstName equals 'Robert' + // using 'MyCustomIndex::class' + $employees = $session + ->advanced() + ->documentQuery(Employee::class, MyCustomIndex::class) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/FilterByNonExistingField.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/FilterByNonExistingField.php new file mode 100644 index 0000000000..31deebc8f7 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/FilterByNonExistingField.php @@ -0,0 +1,106 @@ +openSession(); + try { + # region whereNotExists_1 + /** @var array $ordersWithoutFreightField */ + $ordersWithoutFreightField = $session + ->advanced() + // Define a DocumentQuery on 'Orders' collection + ->documentQuery(Order::class) + // Search for documents that do Not contain field 'Freight' + ->not() + ->whereExists("Freight") + // Execute the query + ->toList(); + + // Results will be only the documents that do Not contain the 'Freight' field in 'Orders' collection + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region whereNotexists_2 + // Query the index + // =============== + + /** @var array $ordersWithoutFreightField */ + $ordersWithoutFreightField = $session + ->advanced() + // Define a DocumentQuery on the index + ->documentQuery(IndexEntry::class, Orders_ByFright::class) + // Verify the index is not stale (optional) + ->waitForNonStaleResults() + // Search for documents that do Not contain field 'Freight' + ->not() + ->whereExists("Freight") + // Execute the query + ->toList(); + + // Results will be only the documents that do Not contain the 'Freight' field in 'Orders' collection + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +# region the_index +// Define a static index on the 'Orders' collection +// ================================================ + +class IndexEntry +{ + // Define the index-fields + public ?float $freight = null; + public ?string $id = null; + + public function getFreight(): float + { + return $this->freight; + } + + public function setFreight(float $freight): void + { + $this->freight = $freight; + } + + public function getId(): ?string + { + return $this->id; + } + + public function setId(?string $id): void + { + $this->id = $id; + } +} + +class Orders_ByFright extends AbstractIndexCreationTask +{ + public function __construct() + { + parent::__construct(); + // Define the index Map function + $this->map = "orders => from doc in orders select new {\n" . + " freight = doc.name, \n" . + " id = doc.id\n" . + "})"; + + } + } +# endregion diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToCustomize.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToCustomize.php new file mode 100644 index 0000000000..7d7f961343 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToCustomize.php @@ -0,0 +1,178 @@ +openSession(); + try { + # region customize_1_1 + $session->advanced()->addBeforeQueryListener(function ($sender, BeforeQueryEventArgs $event) { + $event->getQueryCustomization() + ->addBeforeQueryExecutedListener(function($q) { + // set 'pageSize' to 10 + $q->setPageSize(10); + }); + }); + + $session->query(Employee::class)->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region customize_1_1_0 + $queryDuration = null; + + $session->query(Employee::class) + ->addAfterQueryExecutedListener(function($result) use (&$queryDuration) { + $queryDuration = Duration::ofMillis($result->getDurationInMs()); + }) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region customize_2_1 + $session->advanced() + ->addBeforeQueryListener(function($sender, BeforeQueryEventArgs $event) { + $event->getQueryCustomization()->noCaching(); + }); + + $results = $session->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region customize_3_1 + $session->advanced() + ->addBeforeQueryListener(function($sender, BeforeQueryEventArgs $event) { + $event->getQueryCustomization()->noTracking(); + }); + + $results = $session->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region customize_4_1 + $session->advanced() + ->addBeforeQueryListener(function($sender, BeforeQueryEventArgs $event) { + $event->getQueryCustomization()->randomOrdering(); + }); + + // Result will be ordered randomly each time + $results = $session->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region customize_8_1 + $session->advanced() + ->addBeforeQueryListener(function($sender, BeforeQueryEventArgs $event) { + $event->getQueryCustomization()->waitForNonStaleResults(); + }); + + $results = $session->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projectionbehavior_query + $session->advanced() + ->addBeforeQueryListener(function($sender, BeforeQueryEventArgs $event) { + $event->getQueryCustomization()->projection(ProjectionBehavior::default()); + }); + + $results = $session->query(Employee::class) + ->selectFields(Employee::class, "name") + ->toList(); + # endregion + + $session->saveChanges(); + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToFilterByField.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToFilterByField.php new file mode 100644 index 0000000000..0a56e122e6 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToFilterByField.php @@ -0,0 +1,36 @@ + $results */ + $results = $session + ->advanced() + ->documentQuery(Employee::class) + ->whereExists("FirstName") + ->toList(); + # endregion + + # region whereexists_3 + $results = $session + ->advanced() + ->documentQuery(Employee::class) + ->whereExists("Address.Location.Latitude") + ->toList(); + # endregion + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToGetQueryStatistics.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToGetQueryStatistics.php new file mode 100644 index 0000000000..a2142973a8 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToGetQueryStatistics.php @@ -0,0 +1,59 @@ +openSession(); + try { + # region stats_3 + $stats = new QueryStatistics(); + + $employees = $session->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->statistics($stats) + ->toList(); + + $totalResults = $stats->getTotalResults(); + $durationInMs = $stats->getDurationInMs(); + # endregion + + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformFacetedSearch.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformFacetedSearch.php new file mode 100644 index 0000000000..8f828a4275 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformFacetedSearch.php @@ -0,0 +1,339 @@ +aggregations = new AggregationArray(); + } + + public function getDisplayFieldName(): ?string + { + return $this->displayFieldName; + } + + public function setDisplayFieldName(?string $displayFieldName): void + { + $this->displayFieldName = $displayFieldName; + } + + public function getOptions(): ?FacetOptions + { + return $this->options; + } + + public function setOptions(?FacetOptions $options): void + { + $this->options = $options; + } + + public function getAggregations(): ?AggregationArray + { + return $this->aggregations; + } + + public function setAggregations(null|array|StringArray $aggregations): void + { + if (is_array($aggregations)) { + $aggregations = AggregationArray::fromArray($aggregations); + } + $this->aggregations = $aggregations; + } + + public abstract function toFacetToken(Closure $addQueryParameter): FacetToken; +} + +class Facet extends FacetBase +{ + /** @SerializedName("FieldName") */ + private string $fieldName; + + public function getFieldName(): string + { + return $this->fieldName; + } + + public function setFieldName(string $fieldName): void + { + $this->fieldName = $fieldName; + } + + public function toFacetToken(Closure $addQueryParameter): FacetToken + { + return FacetToken::create($this, $addQueryParameter); + } +} +//endregion + + +//region facet_7_4 +class RangeFacet extends FacetBase +{ + private ?FacetBase $parent = null; + + /** + * @SerializedName("Ranges") + */ + private StringArray $ranges; + + public function __construct(?FacetBase $parent = null) + { + parent::__construct(); + + $this->parent = $parent; + $this->ranges = new StringArray(); + } + + public function getRanges(): StringArray + { + return $this->ranges; + } + + /** + * @param array|StringArray $ranges + */ + public function setRanges(array|StringArray $ranges): void + { + if (is_array($ranges)) { + $ranges = StringArray::fromArray($ranges); + } + $this->ranges = $ranges; + } + + public function toFacetToken($addQueryParameter): FacetToken + { + if ($this->parent != null) { + return $this->parent->toFacetToken($addQueryParameter); + } + + return FacetToken::create($this, $addQueryParameter); + } +} +//endregion + +//region facet_7_5 +class FacetAggregation +{ + public const NONE = "NONE"; + public const MAX = "MAX"; + public const MIN = "MIN"; + public const AVERAGE = "AVERAGE"; + public const SUM = "SUM"; +} +//endregion + +interface FooInterface +{ + //region facet_1 + /** + * Usage + * - aggregateBy(Callable $builder); + * - aggregateBy(FacetBase $facet); + * - aggregateBy(Facet... $facets); + * + * @param Callable|FacetBase $builderOrFacets + * + * @return AggregationDocumentQueryInterface + */ + public function aggregateBy(...$builderOrFacets): AggregationDocumentQueryInterface; + + public function aggregateUsing(?string $facetSetupDocumentId): AggregationDocumentQueryInterface; + //endregion + + //region facet_7_1 + public function byRanges(?RangeBuilder $range, ?RangeBuilder ...$ranges): FacetOperationsInterface; + + public function byField(string $fieldName): FacetOperationsInterface; + public function withDisplayName(string $displayName): FacetOperationsInterface; + + public function withOptions(FacetOptions $options): FacetOperationsInterface; + + public function sumOn(string $path, ?string $displayName = null): FacetOperationsInterface; + public function minOn(string $path, ?string $displayName = null): FacetOperationsInterface; + public function maxOn(string $path, ?string $displayName = null): FacetOperationsInterface; + public function averageOn(string $path, ?string $displayName = null): FacetOperationsInterface; + //endregion +} + +class Foo1 { + //region facet_7_2 + private FacetTermSortMode $termSortMode; + private bool $includeRemainingTerms = false; + private int $start = 0; + private int $pageSize = 0; + + private const INT_32_MAX = 2147483647; + + public function __construct() { + $this->pageSize = self::INT_32_MAX; + $this->termSortMode = FacetTermSortMode::valueAsc(); + } + + //getters and setters + //endregion +} + +class HowToPerformFacetedSearch +{ + public function samples(): void + { + $store = DocumentStoreHolder::getStore(); + try { + + $session = $store->openSession(); + try { + //region facet_2_1 + $facetOptions = new FacetOptions(); + $facetOptions->setTermSortMode(FacetTermSortMode::countDesc()); + + $facet1 = new Facet(); + $facet1->setFieldName("manufacturer"); + $facet1->setOptions($facetOptions); + + $facet2 = new RangeFacet(); + $facet2->setRanges([ + "cost < 200", + "cost between 200 and 400", + "cost between 400 and 600", + "cost between 600 and 800", + "cost >= 800" + ]); + $facet2->setAggregations([FacetAggregation::AVERAGE, "cost"]); + + $facet3 = new RangeFacet(); + $facet3->setRanges([ + "megapixels < 3", + "megapixels between 3 and 7", + "megapixels between 7 and 10", + "megapixels >= 10" + ]); + + /** @var array $facets */ + $facets = $session + ->query(Camera::class, Query::index("Camera/Costs")) + ->aggregateBy($facet1) + ->andAggregateBy($facet2) + ->andAggregateBy($facet3) + ->execute(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region facet_3_1 + $options = new FacetOptions(); + $options->setTermSortMode(FacetTermSortMode::countDesc()); + + $costBuilder = RangeBuilder::forPath("cost"); + $megapixelsBuilder = RangeBuilder::forPath("megapixels"); + + /** @var array $facetResult */ + $facetResult = $session + ->query(Camera::class, Query::index("Camera/Costs")) + ->aggregateBy(function($builder) use ($options) { + $builder + ->byField("manufacturer") + ->withOptions($options); + }) + ->andAggregateBy(function($builder) use ($costBuilder) { + $builder + ->byRanges( + $costBuilder->isLessThan(200), + $costBuilder->isGreaterThanOrEqualTo(200)->isLessThan(400), + $costBuilder->isGreaterThanOrEqualTo(400)->isLessThan(600), + $costBuilder->isGreaterThanOrEqualTo(600)->isLessThan(800), + $costBuilder->isGreaterThanOrEqualTo(800) + ) + ->averageOn("cost"); + }) + ->andAggregateBy(function($builder) use ($megapixelsBuilder) { + $builder + ->byRanges( + $megapixelsBuilder->isLessThan(3), + $megapixelsBuilder->isGreaterThanOrEqualTo(3)->isLessThan(7), + $megapixelsBuilder->isGreaterThanOrEqualTo(7)->isLessThan(10), + $megapixelsBuilder->isGreaterThanOrEqualTo(10) + ); + }) + ->execute(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region facet_4_1 + $facetSetup = new FacetSetup(); + + $facetManufacturer = new Facet(); + $facetManufacturer->setFieldName("manufacturer"); + $facetSetup->setFacets([$facetManufacturer]); + + $cameraFacet = new RangeFacet(); + $cameraFacet->setRanges([ + "cost < 200", + "cost between 200 and 400", + "cost between 400 and 600", + "cost between 600 and 800", + "cost >= 800" + ]); + + $megapixelsFacet = new RangeFacet(); + $megapixelsFacet->setRanges([ + "megapixels < 3", + "megapixels between 3 and 7", + "megapixels between 7 and 10", + "megapixels >= 10" + ]); + + $facetSetup->setRangeFacets([$cameraFacet, $megapixelsFacet]); + + $session->store($facetSetup, "facets/CameraFacets"); + $session->saveChanges(); + + /** @var array $facets */ + $facets = $session + ->query(Camera::class, Query::index("Camera/Costs")) + ->aggregateUsing("facets/CameraFacets") + ->execute(); + //endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +class Camera +{ + +} \ No newline at end of file diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformGroupByQuery.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformGroupByQuery.php new file mode 100644 index 0000000000..6e7359ff7d --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformGroupByQuery.php @@ -0,0 +1,352 @@ +openSession(); + try { + # region group_by_1 + /** @var array $orders */ + $orders = $session->query(Order::class) + ->groupBy("ShipTo.Country") + ->selectKey("ShipTo.Country", "Country") + ->selectSum(new GroupByField("Lines[].Quantity", "OrderedQuantity")) + ->ofType(CountryAndQuantity::class) + ->toList(); + + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_2 + $results = $session->query(Order::class) + ->groupBy("Employee", "Company") + ->selectKey("Employee", "EmployeeIdentifier") + ->selectKey("Company") + ->selectCount() + ->ofType(CountByCompanyAndEmployee::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_3 + /** @var array $orders */ + $orders = $session->query(Order::class) + ->groupBy("Employee", "Company") + ->selectKey("key()", "EmployeeCompanyPair") + ->selectCount("Count") + ->ofType(CountOfEmployeeAndCompanyPairs::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_4 + /** @var array $products */ + $products = $session->query(Order::class) + ->groupBy(GroupBy::array("Lines[].Product")) + ->selectKey("key()", "Products") + ->selectCount() + ->ofType(ProductsInfo::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_5 + /** @var array $results */ + $results = $session->advanced()->documentQuery(Order::class) + ->groupBy("Lines[].Product", "ShipTo.Country") + ->selectKey("Lines[].Product", "Product") + ->selectKey("ShipTo.Country", "Country") + ->selectCount() + ->ofType(ProductInfo::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_6 + /** @var array $results */ + $results = $session->query(Order::class) + ->groupBy(GroupBy::array("Lines[].Product"), GroupBy::array("Lines[].Quantity")) + ->selectKey("Lines[].Product", "Product") + ->selectKey("Lines[].Quantity", "Quantity") + ->selectCount() + ->ofType(ProductInfo::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_7 + /** @var array $results */ + $results = $session->query(Order::class) + ->groupBy(GroupBy::array("Lines[].Product")) + ->selectKey("key()", "Products") + ->selectCount() + ->ofType(ProductsInfo::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_8 + /** @var array $results */ + $results = $session->query(Order::class) + ->groupBy(GroupBy::array("Lines[].Product"), GroupBy::field("ShipTo.Country")) + ->selectKey("Lines[].Product", "Products") + ->selectKey("ShipTo.Country", "Country") + ->selectCount() + ->ofType(ProductsInfo::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region group_by_9 + /** @var array $results */ + $results = $session->query(Order::class) + ->groupBy(GroupBy::array("Lines[].Product"), GroupBy::array("Lines[].Quantity")) + ->selectKey("Lines[].Product", "Products") + ->selectKey("Lines[].Quantity", "Quantities") + ->selectCount() + ->ofType(ProductsInfo::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +class CountByCompanyAndEmployee +{ + private ?int $count = null; + private ?string $company = null; + private ?string $employeeIdentifier = null; + + public function getCount(): ?int + { + return $this->count; + } + + public function setCount(?int $count): void + { + $this->count = $count; + } + + public function getCompany(): ?string + { + return $this->company; + } + + public function setCompany(?string $company): void + { + $this->company = $company; + } + + public function getEmployeeIdentifier(): ?string + { + return $this->employeeIdentifier; + } + + public function setEmployeeIdentifier(?string $employeeIdentifier): void + { + $this->employeeIdentifier = $employeeIdentifier; + } +} + +class Order +{ + +} + +class CountryAndQuantity +{ + private ?string $country = null; + private ?int $orderedQuantity = null; + + public function getCountry(): ?string + { + return $this->country; + } + + public function setCountry(?string $country): void + { + $this->country = $country; + } + + public function getOrderedQuantity(): ?int + { + return $this->orderedQuantity; + } + + public function setOrderedQuantity(?int $orderedQuantity): void + { + $this->orderedQuantity = $orderedQuantity; + } +} + +class EmployeeAndCompany +{ + private ?string $employee = null; + private ?string $company = null; + + public function getEmployee(): ?string + { + return $this->employee; + } + + public function setEmployee(?string $employee): void + { + $this->employee = $employee; + } + + public function getCompany(): ?string + { + return $this->company; + } + + public function setCompany(?string $company): void + { + $this->company = $company; + } +} + +class CountOfEmployeeAndCompanyPairs +{ + private ?EmployeeAndCompany $employeeCompanyPair = null; + private ?int $count = null; + + public function getEmployeeCompanyPair(): ?EmployeeAndCompany + { + return $this->employeeCompanyPair; + } + + public function setEmployeeCompanyPair(?EmployeeAndCompany $employeeCompanyPair): void + { + $this->employeeCompanyPair = $employeeCompanyPair; + } + + public function getCount(): ?int + { + return $this->count; + } + + public function setCount(?int $count): void + { + $this->count = $count; + } +} + +class ProductInfo +{ + private ?int $count = null; + private ?string $product = null; + private ?int $quantity = null; + + public function getCount(): ?int + { + return $this->count; + } + + public function setCount(?int $count): void + { + $this->count = $count; + } + + public function getProduct(): ?string + { + return $this->product; + } + + public function setProduct(?string $product): void + { + $this->product = $product; + } + + public function getQuantity(): ?int + { + return $this->quantity; + } + + public function setQuantity(?int $quantity): void + { + $this->quantity = $quantity; + } +} + +class ProductsInfo +{ + private ?int $count = null; + private ?StringArray $products = null; + private ?int $quantity = null; + + public function getCount(): ?int + { + return $this->count; + } + + public function setCount(?int $count): void + { + $this->count = $count; + } + + public function getProducts(): ?StringArray + { + return $this->products; + } + + public function setProducts(?StringArray $products): void + { + $this->products = $products; + } + + public function getQuantity(): ?int + { + return $this->quantity; + } + + public function setQuantity(?int $quantity): void + { + $this->quantity = $quantity; + } + +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformQueriesLazily.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformQueriesLazily.php new file mode 100644 index 0000000000..c13f276224 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToPerformQueriesLazily.php @@ -0,0 +1,122 @@ +openSession(); + try { + # region lazy_2 + /** @var Lazy> $employeesLazy */ + $employeesLazy = $session + ->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->lazily(); + + /** @var array $employees */ + $employees = $employeesLazy->getValue(); // query will be executed here + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region lazy_5 + /** @var Lazy $countLazy */ + $countLazy = $session + ->query(Employee::class) + ->whereEquals("FirstName", "Robert") + ->countLazily(); + + /** @var int $count */ + $count = $countLazy->getValue(); // query will be executed here + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region lazy_7 + /** @var Lazy> $suggestLazy */ + $suggestLazy = $session + ->query(Employee::class, Query::index("Employees_ByFullName")) + ->suggestUsing(function($builder) { $builder->byField("FullName", "johne"); }) + ->executeLazy(); + + /** @var array $suggest */ + $suggest = $suggestLazy->getValue(); // query will be executed here + + /** @var array $suggestions */ + $suggestions = $suggest["FullName"]->getSuggestions(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region lazy_9 + /** @var Lazy> $facetsLazy */ + $facetsLazy = $session + ->query(Camera::class, Query::index("Camera/Costs")) + ->aggregateUsing("facets/CameraFacets") + ->executeLazy(); + + /** @var array $facets */ + $facets = $facetsLazy->getValue(); // query will be executed here + + /** @var FacetResult $results */ + $results = $facets["manufacturer"]; + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php new file mode 100644 index 0000000000..9ad9c7de26 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php @@ -0,0 +1,241 @@ +openSession(); + try { + # region projections_1 + // request name, city and country for all entities from 'Companies' collection + $queryData = new QueryData( + [ "Name", "Address.city", "Address.country"], + [ "Name", "City", "Country"] + ); + + /** @var array $results */ + $results = $session + ->query(Company::class) + ->selectFields(NameCityAndCountry::class, $queryData) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_2 + $queryData = new QueryData( + [ "ShipTo", "Lines[].ProductName" ], + [ "ShipTo", "Products" ] + ); + + /** @var array $results */ + $results = $session->query(Order::class) + ->selectFields(ShipToAndProducts::class, $queryData) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_3 + /** @var array $results */ + $results = $session->advanced()->rawQuery(FullName::class, "from Employees as e " . + "select {" . + " FullName : e.FirstName + \" \" + e.LastName " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_4 + /** @var array $results */ + $results = $session->advanced()->rawQuery(Total::class, "from Orders as o " . + "select { " . + " Total : o.Lines.reduce( " . + " (acc , l) => acc += l.PricePerUnit * l.Quantity, 0) " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_5 + /** @var array $results */ + $results = $session->advanced()->rawQuery(OrderProjection::class, "from Orders as o " . + "load o.Company as c " . + "select { " . + " CompanyName: c.Name," . + " ShippedAt: o.ShippedAt" . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_6 + /** @var array $results */ + $results = $session->advanced()->rawQuery(EmployeeProjection::class, "from Employees as e " . + "select { " . + " DayOfBirth : new Date(Date.parse(e.Birthday)).getDate(), " . + " MonthOfBirth : new Date(Date.parse(e.Birthday)).getMonth() + 1, " . + " Age : new Date().getFullYear() - new Date(Date.parse(e.Birthday)).getFullYear() " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_7 + /** @var array $results */ + $results = $session->advanced()->rawQuery(EmployeeProjection::class, "from Employees as e " . + "select { " . + " Date : new Date(Date.parse(e.Birthday)), " . + " Name : e.FirstName.substr(0,3) " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_8 + /** @var array $results */ + $results = $session->query(Company::class, Companies_ByContact::class) + ->selectFields(ContactDetails::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_10 + // query index 'Products_BySupplierName' + // return documents from collection 'Products' that have a supplier 'Norske Meierier' + // project them to 'Products' + /** @var array $results */ + $results = $session->query(Products_BySupplierName_Result::class, Products_BySupplierName::class) + ->whereEquals("Name", "Norske Meierier") + ->ofType(Product::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_12 + /** @var array $results */ + $results = $session->advanced()->rawQuery(Employee::class, "declare function output(e) { " . + " var format = function(p){ return p.FirstName + \" \" + p.LastName; }; " . + " return { FullName : format(e) }; " . + "} " . + "from Employees as e select output(e)") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_13 + /** @var array $results */ + $results = $session->advanced()->rawQuery(Employee::class, "from Employees as e " . + "select {" . + " Name : e.FirstName, " . + " Metadata : getMetadata(e)" . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +# region projections_9_0 +class Companies_ByContact extends AbstractIndexCreationTask +{ + public function __construct() + { + parent::__construct(); + + $this->map = "from c in docs.Companies select new { Name = c.Contact.Name, Phone = c.Phone } "; + + $this->storeAllFields(FieldStorage::yes()); // name and phone fields can be retrieved directly from index + } +} +# endregion + +# region projections_9_1 +class ContactDetails +{ + private ?string $name = null; + private ?string $phone = null; + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): void + { + $this->name = $name; + } + + public function getPhone(): ?string + { + return $this->phone; + } + + public function setPhone(?string $phone): void + { + $this->phone = $phone; + } +} +# endregion + +# region projections_11 +class Products_BySupplierName extends AbstractIndexCreationTask +{ +} + +class Products_BySupplierName_Result +{ +} +# endregion diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToQuery.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToQuery.php new file mode 100644 index 0000000000..05473968a6 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToQuery.php @@ -0,0 +1,144 @@ +openSession(); + try { + # region query_1_1 + // This is a Full Collection Query + // No auto-index is created since no filtering is applied + + $allEmployees = $session + ->query(Employee::class) // Query for all documents from 'Employees' collection + ->toList(); // Execute the query + + // All 'Employee' entities are loaded and will be tracked by the session + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region query_2_1 + // Query collection by document ID + // No auto-index is created when querying only by ID + + $employee = $session + ->query(Employee::class) + ->whereEquals("Id", "employees/1-A") // Query for specific document from 'Employees' collection + ->firstOrDefault(); // Execute the query + + // The resulting 'Employee' entity is loaded and will be tracked by the session + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region query_3_1 + // Query collection - filter by document field + + // An auto-index will be created if there isn't already an existing auto-index + // that indexes this document field + + $employees = $session + ->query(Employee::class) + ->whereEquals("FirstName", "Robert") // Query for all 'Employee' documents that match this predicate + ->ToList(); // Execute the query + + // The resulting 'Employee' entities are loaded and will be tracked by the session + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region query_4_1 + // Query collection - page results + // No auto-index is created since no filtering is applied + + $products = $session + ->query(Product::class) + ->skip(5) // Skip first 5 results + ->take(10) // Load up to 10 entities from 'Products' collection + ->toList(); // Execute the query + + // The resulting 'Product' entities are loaded and will be tracked by the session + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region query_5_1 + // Query with DocumentQuery - filter by document field + + // An auto-index will be created if there isn't already an existing auto-index + // that indexes this document field + + $employees = $session + ->advanced()->documentQuery(Employee::class) // Use DocumentQuery + ->whereEquals("FirstName", "Robert") // Query for all 'Employee' documents that match this predicate + ->toList(); // Execute the query + + // The resulting 'Employee' entities are loaded and will be tracked by the session + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region query_6_1 + // Query with RawQuery - filter by document field + + // An auto-index will be created if there isn't already an existing auto-index + // that indexes this document field + + $employees = $session + // Provide RQL to RawQuery + ->advanced()->rawQuery(Employee::class, "from 'Employees' where FirstName = 'Robert'") + // Execute the query + ->toList(); + + // The resulting 'Employee' entities are loaded and will be tracked by the session + # endregion + } finally { + $session->close(); + } + + } finally { + $store->close(); + } + } +} + +interface FooInterface +{ + # region syntax + // Methods for querying a collection OR an index: + // ================================================ + + public function query(?string $className, $collectionOrIndexName = null): DocumentQueryInterface; + + public function documentQuery(?string $className, $indexNameOrClass = null, ?string $collectionName = null, bool $isMapReduce = false): DocumentQueryInterface; + + // RawQuery: + // ========= + public function rawQuery(?string $className, string $query): RawDocumentQueryInterface; + # endregion +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToUseIntersect.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToUseIntersect.php new file mode 100644 index 0000000000..f9e02f62bd --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToUseIntersect.php @@ -0,0 +1,54 @@ +openSession(); + try { + # region intersect_2 + // return all T-shirts that are manufactured by 'Raven' + // and contain both 'Small Blue' and 'Large Gray' types + /** @var array $tShirts */ + $tShirts = $session + ->query(TShirt::class, TShirts_ByManufacturerColorSizeAndReleaseYear::class) + ->whereEquals("manufacturer", "Raven") + ->intersect() + ->whereEquals("color", "Blue") + ->andAlso() + ->whereEquals("size", "Small") + ->intersect() + ->whereEquals("color", "Gray") + ->andAlso() + ->whereEquals("size", "Large") + ->toList(); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +class TShirt { + +} + +class TShirts_ByManufacturerColorSizeAndReleaseYear extends AbstractIndexCreationTask +{ +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToWorkWithSuggestions.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToWorkWithSuggestions.php new file mode 100644 index 0000000000..e741414843 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/HowToWorkWithSuggestions.php @@ -0,0 +1,115 @@ +openSession(); + try { + # region suggest_5 + $options = new SuggestionOptions(); + $options->setAccuracy(0.4); + $options->setPageSize(5); + $options->setDistance(StringDistanceTypes::jaroWinkler()); + $options->setSortMode(SuggestionSortMode::popularity()); + + /** @var array $suggestions */ + $suggestions = $session + ->query(Employee::class, Employees_ByFullName::class) + ->suggestUsing(function($builder) use ($options) { + $builder->byField("FullName", "johne") + ->withOptions($options); + }) + ->execute(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region suggest_8 + $suggestionWithTerm = new SuggestionWithTerm("FullName"); + $suggestionWithTerm->setTerm("johne"); + + /** @var array $suggestions */ + $suggestions = $session + ->query(Employee::class, Employees_ByFullName::class) + ->suggestUsing($suggestionWithTerm) + ->execute(); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php new file mode 100644 index 0000000000..1f2a8a4e55 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php @@ -0,0 +1,196 @@ +openSession(); + try { + //region spatial_4 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->withinRadius(10, 32.1234, 23.4321); } + ) + ->toList(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region spatial_5 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + // this equals to WithinRadius(10, 32.1234, 23.4321) + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->relatesToShape("Circle(32.1234 23.4321 d=10.0000)", SpatialRelation::within()); } + ) + ->toList(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region spatial_7 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + // sort results by distance from 32.1234 latitude and 23.4321 longitude point + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->withinRadius(10, 32.1234, 23.4321); } + ) + ->orderByDistance( + new PointField("latitude", "longtude"), + 32.12324, 23.4321) + ->toList(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region spatial_9 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + // sort results by distance from 32.1234 latitude and 23.4321 longitude point + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->withinRadius(10, 32.1234, 23.4321); } + ) + ->orderByDistanceDescending( + new PointField("latitude", "longtude"), + 32.12324, 23.4321) + ->toList(); + //endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +class House { + private ?string $name = null; + private ?float $latitude = null; + private ?float $longitude = null; + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): void + { + $this->name = $name; + } + + public function getLatitude(): ?float + { + return $this->latitude; + } + + public function setLatitude(?float $latitude): void + { + $this->latitude = $latitude; + } + + public function getLongitude(): ?float + { + return $this->longitude; + } + + public function setLongitude(?float $longitude): void + { + $this->longitude = $longitude; + } +} \ No newline at end of file diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/MoreLikeThis.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/MoreLikeThis.php new file mode 100644 index 0000000000..cf9b6f7527 --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/MoreLikeThis.php @@ -0,0 +1,156 @@ +id; + } + + public function setId(?string $id): void + { + $this->id = $id; + } + + public function getCategory(): ?string + { + return $this->category; + } + + public function setCategory(?string $category): void + { + $this->category = $category; + } +} + +class MoreLikeThis +{ + public function samples(): void + { + $store = DocumentStoreHolder::getStore(); + try { + + $session = $store->openSession(); + try { + # region more_like_this_4 + // Search for similar articles to 'articles/1' + // using 'Articles/MoreLikeThis' index and search only field 'body' + $options = new MoreLikeThisOptions(); + $options->setFields([ "body" ]); + + /** @var array
$articles */ + $articles = $session + ->query(Article::class, Query::index("Articles/MoreLikeThis")) + ->moreLikeThis(function($builder) use ($options) { + $builder + ->usingDocument(function ($x) { + $x->whereEquals("id()", "articles/1"); + }) + ->withOptions($options); + }) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region more_like_this_6 + // Search for similar articles to 'articles/1' + // using 'Articles/MoreLikeThis' index and search only field 'body' + // where article category is 'IT' + $options = new MoreLikeThisOptions(); + $options->setFields([ "body" ]); + /** @var array
$articles */ + $articles = $session + ->query(Article::class, Query::index("Articles/MoreLikeThis")) + ->moreLikeThis(function($builder) use ($options) { + $builder + ->usingDocument(function ($x) { + $x->whereEquals("id()", "articles/1"); + }) + ->withOptions($options); + }) + ->whereEquals("category", "IT") + ->toList(); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/5.4/Samples/php/ClientApi/session/Querying/SortQueryResults.php b/Documentation/5.4/Samples/php/ClientApi/session/Querying/SortQueryResults.php new file mode 100644 index 0000000000..47ec58502f --- /dev/null +++ b/Documentation/5.4/Samples/php/ClientApi/session/Querying/SortQueryResults.php @@ -0,0 +1,440 @@ +openSession(); + try { + // Order by document field + // ======================= + + # region sort_1 + /** @var array $products */ + $products = $session + // Make a dynamic query on the Products collection + ->query(Product::class) + // Apply filtering (optional) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'OrderBy', pass the document-field by which to order the results + ->orderBy("UnitsInStock") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value in ascending order, + // with smaller values listed first. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_3 + /** @var array $products */ + $products = $session->advanced() + // Make a DocumentQuery on the Products collection + ->documentQuery(Product::class) + // Apply filtering (optional) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'OrderBy', pass the document-field by which to order the results + ->orderBy("UnitsInStock") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value in ascending order, + // with smaller values listed first. + # endregion + } finally { + $session->close(); + } + + // Order by score + // ============== + + $session = $store->openSession(); + try { + # region sort_4 + /** @var array $products */ + $products = $session + ->query(Product::class) + // Apply filtering + ->whereLessThan("UnitsInStock", 5) + ->orElse() + ->whereEquals("Discontinued", true) + // Call 'orderByScore' + ->orderByScore() + ->toList(); + + // Results will be sorted by the score value + // with best matching documents (higher score values) listed first. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_6 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + // Apply filtering + ->whereLessThan("UnitsInStock", 5) + ->orElse() + ->whereEquals("Discontinued", true) + // Call 'orderByScore' + ->orderByScore() + ->toList(); + + // Results will be sorted by the score value + // with best matching documents (higher score values) listed first. + # endregion + } finally { + $session->close(); + } + + // Order by random + // =============== + + $session = $store->openSession(); + try { + # region sort_7 + /** @var array $products */ + $products = $session->query(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'randomOrdering' + ->randomOrdering() + // An optional seed can be passed, e.g.: + // ->randomOrdering('someSeed') + ->toList(); + + // Results will be randomly ordered. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_9 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'randomOrdering' + ->randomOrdering() + // An optional seed can be passed, e.g.: + // ->randomOrdering('someSeed') + ->toList(); + + // Results will be randomly ordered. + # endregion + } finally { + $session->close(); + } + + // Order by Count + // ============== + + $session = $store->openSession(); + try { + # region sort_10 + $numberOfProductsPerCategory = $session + ->query(Product::class) + // Make an aggregation query + ->groupBy("Category") + ->selectKey("Category") + // Count the number of product documents per category + ->selectCount() + // Order by the Count value + // Here you need to specify the ordering type explicitly + ->orderBy("Count", OrderingType::long()) + ->toList(); + + // Results will contain the number of Product documents per category + // ordered by that count in ascending order. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_12 + $numberOfProductsPerCategory = $session->advanced() + ->documentQuery(Product::class) + // Group by Category + ->groupBy("Category") + ->selectKey("Category") + // Count the number of product documents per category + ->selectCount() + // Order by the Count value + // Here you need to specify the ordering type explicitly + ->orderBy("Count", OrderingType::long()) + ->toList(); + + // Results will contain the number of Product documents per category + // ordered by that count in ascending order. + # endregion + } finally { + $session->close(); + } + + // Order by Sum + // ============ + + $session = $store->openSession(); + try { + # region sort_13 + $numberOfUnitsInStockPerCategory = $session + ->query(Product::class) + // Make an aggregation query + // Group by Category + ->groupBy("Category") + // Order by the Sum value + ->selectKey("Category") + ->selectSum(new GroupByField("UnitsInStock", "Sum")) + ->orderBy("Sum") + ->toList(); + + // Results will contain the total number of units in stock per category + // ordered by that number in ascending order. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_15 + $numberOfUnitsInStockPerCategory = $session->advanced() + ->documentQuery(Product::class) + // Group by Category + ->groupBy("Category") + ->selectKey("Category") + // Sum the number of units in stock per category + ->selectSum(new GroupByField("UnitsInStock", "Sum")) + // Order by the Sum value + // Here you need to specify the ordering type explicitly + ->orderBy("Sum", OrderingType::long()) + ->toList(); + + // Results will contain the total number of units in stock per category + // ordered by that number in ascending order. + # endregion + } finally { + $session->close(); + } + + // Force ordering type + // =================== + + $session = $store->openSession(); + try { + # region sort_16 + /** @var array $products */ + $products = $session + ->query(Product::class) + // Call 'OrderBy', order by field 'QuantityPerUnit' + // Pass a second param, requesting to order the text alphanumerically + ->orderBy("QuantityPerUnit", OrderingType::alphaNumeric()) + ->toList(); + # endregion + + # region sort_16_results + // Running the above query on the NorthWind sample data, + // would produce the following order for the QuantityPerUnit field: + // ================================================================ + + // "1 kg pkg." + // "1k pkg." + // "2 kg box." + // "4 - 450 g glasses" + // "5 kg pkg." + // ... + + // While running with the default Lexicographical ordering would have produced: + // ============================================================================ + + // "1 kg pkg." + // "10 - 200 g glasses" + // "10 - 4 oz boxes" + // "10 - 500 g pkgs." + // "10 - 500 g pkgs." + // ... + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_18 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + // Call 'OrderBy', order by field 'QuantityPerUnit' + // Pass a second param, requesting to order the text alphanumerically + ->orderBy("QuantityPerUnit", OrderingType::alphaNumeric()) + ->toList(); + # endregion + } finally { + $session->close(); + } + + // Chain ordering + // ============== + + $session = $store->openSession(); + try { + # region sort_19 + /** @var array $products */ + $products = $session + ->query(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Apply the primary sort by 'UnitsInStock' + ->orderByDescending("UnitsInStock") + // Apply a secondary sort by the score (for products with the same # of units in stock) + ->orderByScore() + // Apply another sort by 'Name' (for products with same # of units in stock and same score) + ->orderBy("Name") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value (descending), + // then by score, + // and then by 'Name' (ascending). + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_21 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Apply the primary sort by 'UnitsInStock' + ->orderByDescending("UnitsInStock") + // Apply a secondary sort by the score + ->orderByScore() + // Apply another sort by 'Name' + ->orderBy("Name") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value (descending), + // then by score, + // and then by 'Name' (ascending). + # endregion + } finally { + $session->close(); + } + + // Custom sorters + // ============== + + $session = $store->openSession(); + try { + # region sort_22 + /** @var array $products */ + $products = $session + ->query(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Order by field 'UnitsInStock', pass the name of your custom sorter class + ->orderBy("UnitsInStock", "MySorter") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value + // according to the logic from 'MySorter' class + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_24 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Order by field 'UnitsInStock', pass the name of your custom sorter class + ->orderBy("UnitsInStock", "MySorter") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value + // according to the logic from 'MySorter' class + # endregion + } finally { + $session->close(); + } + + // Get score from metadata + // ======================= + + $session = $store->openSession(); + try { + # region get_score_from_metadata + // Make a query: + // ============= + + $employees = $session + ->query(Employee::class) + ->search("Notes", "English") + ->search("Notes", "Italian") + ->boost(10) + ->toList(); + + // Get the score: + // ============== + + // Call 'GetMetadataFor', pass an entity from the resulting employees list + $metadata = $session->advanced()->getMetadataFor($employees[0]); + + // Score is available in the 'INDEX_SCORE' metadata property + $score = $metadata[DocumentsMetadata::INDEX_SCORE]; + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} diff --git a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.dotnet.markdown b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.dotnet.markdown index 25da14f03e..ff964ed894 100644 --- a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.dotnet.markdown +++ b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.dotnet.markdown @@ -6,8 +6,8 @@ * Applying a projection in a query allows you to shape the query results to meet specific requirements, delivering just the data needed instead of the original full document content. -* This article provides examples of projecting query results when making a __dynamic-query__. - For projecting results when querying a __static-index__ see [project index query results](../../../indexes/querying/projections). +* This article provides examples of projecting query results when making a **dynamic-query**. + For projecting results when querying a **static-index** see [project index query results](../../../indexes/querying/projections). * In this page: @@ -28,7 +28,7 @@ ### What are projections: -* A projection refers to the __transformation of query results__ into a customized structure, +* A projection refers to the **transformation of query results** into a customized structure, modifying the shape of the data returned by the server. * Instead of retrieving the full document from the server and then picking relevant data from it on the client, diff --git a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.js.markdown b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.js.markdown index 519e5a9828..89e0001c9b 100644 --- a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.js.markdown +++ b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.js.markdown @@ -6,8 +6,8 @@ * Applying a projection in a query allows you to shape the query results to meet specific requirements, delivering just the data needed instead of the original full document content. -* This article provides examples of projecting query results when making a __dynamic-query__. - For projecting results when querying a __static-index__ see [project index query results](../../../indexes/querying/projections). +* This article provides examples of projecting query results when making a **dynamic-query**. + For projecting results when querying a **static-index** see [project index query results](../../../indexes/querying/projections). * In this page: @@ -27,9 +27,9 @@ --- -__What are projections__: +**What are projections**: -* A projection refers to the __transformation of query results__ into a customized structure, +* A projection refers to the **transformation of query results** into a customized structure, modifying the shape of the data returned by the server. * Instead of retrieving the full document from the server and then picking relevant data from it on the client, @@ -43,7 +43,7 @@ __What are projections__: --- -__When to use projections__: +**When to use projections**: * Projections allow you to tailor the query results specifically to your needs. Getting specific details to display can be useful when presenting data to users or populating user interfaces. @@ -62,7 +62,7 @@ __When to use projections__: --- -__Projections are not tracked by the session__: +**Projections are not tracked by the session**: * On the client side, the resulting projected entities returned by the query are Not tracked by the Session. @@ -70,7 +70,7 @@ __Projections are not tracked by the session__: --- -__Projections are the final stage in the query pipeline__: +**Projections are the final stage in the query pipeline**: * Projections are applied as the last stage in the query pipeline, after the query has been processed, filtered, sorted, and paged. @@ -83,7 +83,7 @@ __Projections are the final stage in the query pipeline__: --- -__The cost of projections__: +**The cost of projections**: * Queries in RavenDB do not allow any computation to occur during the query phase. However, you can perform any [calculations](../../../client-api/session/querying/how-to-project-query-results#projectionWithCalculations) inside the projection. @@ -105,7 +105,7 @@ __The cost of projections__: {NOTE: } -__Example I - Projecting individual fields of the document__: +**Example I - Projecting individual fields of the document**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_1@client-api\session\querying\howToProjectQueryResults.js /} @@ -119,7 +119,7 @@ select Name, Address.City, Address.Country {NOTE: } -__Example II - Projecting individual fields with alias__: +**Example II - Projecting individual fields with alias**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_2@client-api\session\querying\howToProjectQueryResults.js /} @@ -133,7 +133,7 @@ select Name as CompanyName, Address.City as City, Address.Country as Country {NOTE: } -__Example III - Projecting arrays and objects__: +**Example III - Projecting arrays and objects**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_3@client-api\session\querying\howToProjectQueryResults.js /} @@ -155,7 +155,7 @@ select { {NOTE: } -__Example IV - Projection with expression__: +**Example IV - Projection with expression**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_4@client-api\session\querying\howToProjectQueryResults.js /} @@ -171,7 +171,7 @@ select { {NOTE: } - __Example V - Projection with calculations__: + **Example V - Projection with calculations**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_5@client-api\session\querying\howToProjectQueryResults.js /} @@ -191,7 +191,7 @@ select { {NOTE: } -__Example VI - Projecting using functions__: +**Example VI - Projecting using functions**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_6@client-api\session\querying\howToProjectQueryResults.js /} @@ -208,7 +208,7 @@ from "employees" as e select output(e) {NOTE: } -__Example VII - Projecting using a loaded document__: +**Example VII - Projecting using a loaded document**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_7@client-api\session\querying\howToProjectQueryResults.js /} @@ -226,7 +226,7 @@ select { {NOTE: } -__Example VIII - Projection with dates__: +**Example VIII - Projection with dates**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_8@client-api\session\querying\howToProjectQueryResults.js /} @@ -244,7 +244,7 @@ select { {NOTE: } -__Example IX - Projection with metadata__: +**Example IX - Projection with metadata**: {CODE-TABS} {CODE-TAB:nodejs:Query projections_9@client-api\session\querying\howToProjectQueryResults.js /} @@ -272,7 +272,7 @@ the metadata field `@nested-object-types` from the document will be automaticall // ===================================================== from "users" -select name, @metadata.@nested-object-types as __PROJECTED_NESTED_OBJECT_TYPES__ +select name, @metadata.@nested-object-types as **PROJECTED_NESTED_OBJECT_TYPES** {CODE-BLOCK/} {CODE:nodejs projections_10_results@client-api\session\querying\howToProjectQueryResults.js /} @@ -285,11 +285,11 @@ select name, @metadata.@nested-object-types as __PROJECTED_NESTED_OBJECT_TYPES__ | Parameter | Type | Description | |------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| __property__ | `string` | Field name to project | -| __properties__ | `string[]` | List of field names to project | -| __queryData__ | `QueryData` | Object with projection query definitions | -| __projectionClass__ | `object` | The class type of the projected fields | -| __projectionBehavior__ | `string` | Projection behavior is useful when querying a static-index.
Learn more in [projection behavior with indexes](../../../indexes/querying/projections). | +| **property** | `string` | Field name to project | +| **properties** | `string[]` | List of field names to project | +| **queryData** | `QueryData` | Object with projection query definitions | +| **projectionClass** | `object` | The class type of the projected fields | +| **projectionBehavior** | `string` | Projection behavior is useful when querying a static-index.
Learn more in [projection behavior with indexes](../../../indexes/querying/projections). | {PANEL/} diff --git a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown new file mode 100644 index 0000000000..cbc87fd3f0 --- /dev/null +++ b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.php.markdown @@ -0,0 +1,236 @@ +# Project Query Results +--- + +{NOTE: } + +* Applying a projection in a query allows you to shape the query results to meet specific requirements, + delivering just the data needed instead of the original full document content. + +* This article provides examples of projecting query results when making a **dynamic-query**. + For projecting results when querying a **static-index** see [project index query results](../../../indexes/querying/projections). + +* In this page: + + * [Projections overview](../../../client-api/session/querying/how-to-project-query-results#projections-overview) + + * [Projection Methods](../../../client-api/session/querying/how-to-project-query-results#projection-methods) + * [`select`, `selectFields`](../../../client-api/session/querying/how-to-project-query-results#select,-selectfields) + * [`ofType`](../../../client-api/session/querying/how-to-project-query-results#oftype) + + * [Single projection per query](../../../client-api/session/querying/how-to-project-query-results#single-projection-per-query) + +{NOTE/} + +--- + +{PANEL: Projections overview} + +### What are projections: + +* A projection refers to the **transformation of query results** into a customized structure, + modifying the shape of the data returned by the server. + +* Instead of retrieving the full document from the server and then picking relevant data from it on the client, + you can request a subset of the data, specifying the document fields you want to get from the server. + +* The query can load [related documents](../../../indexes/indexing-related-documents#what-are-related-documents) and have their data merged into the projection results. + +* Objects and arrays can be projected, fields can be renamed, and any calculations can be made within the projection. + +* Content from inner objects and arrays can be projected. + An alias name can be given to the projected fields, and any calculations can be made within the projection. + +### When to use projections: + +* Projections allow you to tailor the query results specifically to your needs. + Getting specific details to display can be useful when presenting data to users or populating user interfaces. + Projection queries are also useful with [subscriptions](../../../client-api/data-subscriptions/what-are-data-subscriptions) + since all transformation work is done on the server side without having to send a lot of data over the wire. + +* Returning partial document data from the server reduces network traffic, + as clients receive only relevant data required for a particular task, enhancing overall performance. + +* Savings can be significant if you need to show just a bit of information from a large document. For example: + the size of the result when querying for all "Orders" documents where "Company" is "companies/65-A" is 19KB. + Performing the same query and projecting only the "Employee" and "OrderedAt" fields results in only 5KB. + +* However, when you need to actively work with the complete set of data on the client side, + then do use a query without a projection to retrieve the full document from the server. + +### Projections are not tracked by the session: + +* On the client side, the resulting projected entities returned by the query are Not tracked by the Session. + +* Any modification made to a projection entity will not modify the corresponding document on the server when _SaveChanges_ is called. + +### Projections are the final stage in the query pipeline: + +* Projections are applied as the last stage in the query pipeline, + after the query has been processed, filtered, sorted, and paged. + +* This means that the projection does Not apply to all the documents in the collection, + but only to the documents matching the query predicate. + +* Within the projection you can only filter what data will be returned from the matching documents, + but you cannot filter which documents will be returned. That has already been determined earlier in the query pipeline. + +* Only a [single projection request](../../../client-api/session/querying/how-to-project-query-results#single-projection-per-query) can be made per query. + +### The cost of projections: + +* Queries in RavenDB do not allow any computation to occur during the query phase. + However, you can perform any [calculations](../../../client-api/session/querying/how-to-project-query-results#example---projection-with-calculations) + inside the projection. + +* But while calculations within a projection are allowed, having a very complex logic can impact query performance. + So RavenDB limits the total time it will spend processing a query and its projections. + Exceeding this time limit will fail the query. This is configurable, see the following configuration keys: + * [Databases.QueryTimeoutInSec](../../../server/configuration/database-configuration#databases.querytimeoutinsec) + * [Databases.QueryOperationTimeoutInSec](../../../server/configuration/database-configuration#databases.queryoperationtimeoutinsec) + +{PANEL/} + +## Projection Methods + +{PANEL: `select`, `selectFields`} + +Projections are commonly performed in PHP using the `select` and `selectFields` methods. +You can specify what fields from a document you want to retrieve and even provide complex expression. + +### Example - Projecting Individual Fields of the Document: + +{CODE-TABS} +{CODE-TAB:php projections_1@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Companies +select Name, Address.City as City, Address.Country as Country +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projecting Arrays and Objects: + +{CODE-TABS} +{CODE-TAB:php projections_2@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from Orders +select ShipTo, Lines[].ProductName as Products +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with expression: + +{CODE-TABS} +{CODE-TAB:php projections_3@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" as e +select { + FullName: e.FirstName + " " + e.LastName +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Calculation: + +{CODE-TABS} +{CODE-TAB:php projections_4@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Orders" as o +select { + Total : o.Lines.reduce( + (acc , l) => acc += l.PricePerUnit * l.Quantity, 0) +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection Using a Loaded Document: + +{CODE-TABS} +{CODE-TAB:php projections_5@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Orders" as o +load o.Company as c +select { + CompanyName: c.Name, + ShippedAt: o.ShippedAt +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Dates: + +{CODE-TABS} +{CODE-TAB:php projections_6@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" as e +select { + DayOfBirth : new Date(Date.parse(e.Birthday)).getDate(), + MonthOfBirth : new Date(Date.parse(e.Birthday)).getMonth() + 1, + Age : new Date().getFullYear() - new Date(Date.parse(e.Birthday)).getFullYear() +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Raw JavaScript Code: + +{CODE-TABS} +{CODE-TAB:php projections_7@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" as e +select { + Date : new Date(Date.parse(e.Birthday)), + Name : e.FirstName.substr(0,3) +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +### Example - Projection with Metadata: + +{CODE-TABS} +{CODE-TAB:php projections_13@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Employees" as e +select { + Name : e.FirstName, + Metadata : getMetadata(e) +} +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: `ofType`} + +`ofType` is a client-side projection that maps results that the server returns into a given type. +This may become useful when querying an index that contains fields that are not available in the mapped type. + +### Example + +{CODE-TABS} +{CODE-TAB:php:Sync projections_10@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TAB:php:Index projections_11@ClientApi\Session\Querying\HowToProjectQueryResults.php /} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Single projection per query} + +As of RavenDB v6.0, only a single projection request can be made per query. +Attempting multiple projection executions in the same query will result in an exception. + +{PANEL/} + +## Related Articles + +### Session + +- [Query Overview](../../../client-api/session/querying/how-to-query) +- [How to Stream Query Results](../../../client-api/session/querying/how-to-stream-query-results) + +### Indexes + +- [Querying an index](../../../indexes/querying/query-index) +- [Project index query results](../../../indexes/querying/projections) + +### Server + +- [JavaScript Engine](../../../server/kb/javascript-engine) diff --git a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown index ad7a14b2fe..bab910bc83 100644 --- a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown +++ b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/how-to-project-query-results.python.markdown @@ -6,8 +6,8 @@ * Applying a projection in a query allows you to shape the query results to meet specific requirements, delivering just the data needed instead of the original full document content. -* This article provides examples of projecting query results when making a __dynamic-query__. - For projecting results when querying a __static-index__ see [project index query results](../../../indexes/querying/projections). +* This article provides examples of projecting query results when making a **dynamic-query**. + For projecting results when querying a **static-index** see [project index query results](../../../indexes/querying/projections). * In this page: @@ -28,7 +28,7 @@ ### What are projections: -* A projection refers to the __transformation of query results__ into a customized structure, +* A projection refers to the **transformation of query results** into a customized structure, modifying the shape of the data returned by the server. * Instead of retrieving the full document from the server and then picking relevant data from it on the client, diff --git a/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown new file mode 100644 index 0000000000..75bd9b912e --- /dev/null +++ b/Documentation/6.0/Raven.Documentation.Pages/client-api/session/querying/sort-query-results.php.markdown @@ -0,0 +1,290 @@ +# Sort Query Results + +--- + +{NOTE: } + +* When making a query, the server will return the results **sorted** only if explicitly requested by the query. + If no sorting method is specified when issuing the query then results will not be sorted. + + * Note: An exception to the above rule is when [Boosting](../../../indexes/boosting) is involved in the query. + Learn more in [Automatic score-based ordering](../../../indexes/boosting#automatic-score-based-ordering). + +* Sorting is applied by the server after the query filtering stage. + Applying filtering is recommended as it reduces the number of results RavenDB needs to sort + when querying a large dataset. + +* Multiple sorting actions can be chained. + +* This article provides examples of sorting query results when making a **dynamic-query**. + For sorting results when querying a **static-index** see [sort index query results](../../../indexes/querying/sorting). + +* In this page: + * [Order by field value](../../../client-api/session/querying/sort-query-results#order-by-field-value) + + * [Order by score](../../../client-api/session/querying/sort-query-results#order-by-score) + * [Get resulting score](../../../client-api/session/querying/sort-query-results#get-resulting-score) + + * [Order by random](../../../client-api/session/querying/sort-query-results#order-by-random) + + * [Order by spatial](../../../client-api/session/querying/sort-query-results#order-by-spatial) + + * [Order by count (aggregation query)](../../../client-api/session/querying/sort-query-results#order-by-count-(aggregation-query)) + + * [Order by sum (aggregation query)](../../../client-api/session/querying/sort-query-results#order-by-sum-(aggregation-query)) + + * [Force ordering type](../../../client-api/session/querying/sort-query-results#force-ordering-type) + + * [Chain ordering](../../../client-api/session/querying/sort-query-results#chain-ordering) + + * [Custom sorters](../../../client-api/session/querying/sort-query-results#custom-sorters) + + * [Syntax](../../../client-api/session/querying/sort-query-results#syntax) + +{NOTE/} + +--- + +{PANEL: Order by field value} + +* Use `orderBy` or `orderByDescending` (see below) to order the results by the specified document field. + +{CODE-TABS} +{CODE-TAB:php:Query sort_1@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_3@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by UnitsInStock as long +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{INFO: } + +**Ordering Type**: + +* By default, the `orderBy` methods will determine the `OrderingType` from the property path expression + and specify that ordering type in the generated RQL that is sent to the server. + +* E.g. in the above example, ordering by `UnitsInStock` will result in `OrderingType::long` + because this property's data type is integer. + +* Different ordering can be forced - see [Force ordering type](../../../client-api/session/querying/sort-query-results#force-ordering-type) below. + +{INFO/} + +{PANEL/} + +{PANEL: Order by score} + +* When querying with some filtering conditions, a basic score is calculated for each item in the results + by the underlying indexing engine. (Read more about Lucene scoring [here](https://lucene.apache.org/core/3_3_0/scoring.html)). + +* The higher the score value the better the match. + +* Use `orderByScore` to order the query results by this score. + +{CODE-TABS} +{CODE-TAB:php:Query sort_4@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_6@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock < 5 or Discontinued == true +order by score() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{INFO: } + +#### Get resulting score: + +--- + +The score details can be retrieved by either: + + * **Request to include explanations**: + You can get the score details and see how it was calculated by requesting to include explanations in the query. + Currently, this is only available when using Lucene as the underlying indexing engine. + Learn more in [Include query explanations](../../../client-api/session/querying/debugging/include-explanations). + + * **Get score from metadata**: + The score is available in the `INDEX_SCORE` metadata property within each result. + The following example shows how to get the score from the metadata of the resulting entities that were loaded to the session: + + {CODE:php get_score_from_metadata@ClientApi\Session\Querying\SortQueryResults.php /} + +{INFO/} + +{PANEL/} + +{PANEL: Order by random} + +* Use `randomOrdering` to randomize the order of the query results. + +* An optional seed parameter can be passed. + +{CODE-TABS} +{CODE-TAB:php:Query sort_7@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_9@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by random() +// order by random(someSeed) +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Order by spatial} + +* If your data contains geographical locations, + spatial query results can be sorted based on their distance from a specific point. + +* See detailed explanation in [Spatial Sorting](../../../client-api/session/querying/how-to-make-a-spatial-query#spatial-sorting). + +{PANEL/} + +{PANEL: Order by count (aggregation query)} + +* The results of a [group-by query](../../../client-api/session/querying/how-to-perform-group-by-query) can be sorted by the `Count` aggregation operation used in the query. + +{CODE-TABS} +{CODE-TAB:php:Query sort_10@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_12@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +group by Category +order by count() as long +select key() as "Category", count() +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Order by sum (aggregation query)} + +* The results of a [group-by query](../../../client-api/session/querying/how-to-perform-group-by-query) can be sorted by the `Sum` aggregation operation used in the query. + +{CODE-TABS} +{CODE-TAB:php:Query sort_13@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_15@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +group by Category +order by Sum as long +select key() as 'Category', sum(UnitsInStock) as Sum +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Force ordering type} + +* By default, the `orderBy` methods will determine the `OrderingType` from the property path expression + and specify that ordering type in the generated RQL that is sent to the server. + +* A different ordering can be forced by passing the ordering type explicitly to `orderBy` or `orderByDescending`. + +* The following ordering types are available: + + * `OrderingType::long` + * `OrderingType::double` + * `OrderingType::alphaNumeric` + * `OrderingType::string` (lexicographic ordering) + +* When using RQL directly, if no ordering type is specified, then the server defaults to lexicographic ordering. + +{NOTE: } + +**Using alphanumeric ordering example**: + +* When ordering mixed-character strings by the default lexicographical ordering + then comparison is done character by character based on the Unicode values. + For example, "Abc9" will come after "Abc10" since 9 is greater than 1. + +* If you want the digit characters to be ordered as numbers then use alphanumeric ordering + where "Abc10" will result after "Abc9". + +{CODE-TABS} +{CODE-TAB:php:Query sort_16@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_18@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +order by QuantityPerUnit as alphanumeric +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{NOTE/} + +{PANEL/} + +{PANEL: Chain ordering} + +* It is possible to chain multiple orderings in the query. + Any combination of secondary sorting is possible as the fields are indexed independently of one another. + +* There is no limit on the number of sorting actions that can be chained. + +{CODE-TABS} +{CODE-TAB:php:Query sort_19@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_21@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by UnitsInStock as long desc, score(), Name +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Custom sorters } + +* The Lucene indexing engine allows you to create your own custom sorters. + Custom sorters can be deployed to the server by either: + + * Sending the [Put Sorters Operation](../../../client-api/operations/maintenance/sorters/put-sorter) from your code. + + * Uploading a custom sorter from Studio, see [Custom Sorters View](../../../studio/database/settings/custom-sorters). + +* Once the custom sorter is deployed, you can sort the query results with it. + +{CODE-TABS} +{CODE-TAB:php:Query sort_22@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB:php:DocumentQuery sort_24@ClientApi\Session\Querying\SortQueryResults.php /} +{CODE-TAB-BLOCK:sql:RQL} +from "Products" +where UnitsInStock > 10 +order by custom(UnitsInStock, "MySorter") +{CODE-TAB-BLOCK/} +{CODE-TABS/} + +{PANEL/} + +{PANEL: Syntax} + +{code:php syntax@ClientApi\Session\Querying\SortQueryResults.php /} + +| Parameter | Type | Description | +|------------|----------|----------------------| +| **$field** | `string` | The field to sort by | +| **$sorterNameOrOrdering** | `string` | The ordering type to sort the results by:
`OrderingType::long`
`OrderingType::double`
`OrderingType::alphaNumeric`
`OrderingType::string` (default) | + +{PANEL/} + +## Related Articles + +#### Client API + +- [Query Overview](../../../client-api/session/querying/how-to-query) + +### Querying + +- [Customize query](../../../client-api/session/querying/how-to-customize-query) +- [Group by query](../../../client-api/session/querying/how-to-perform-group-by-query) +- [Spatial query](../../../client-api/session/querying/how-to-make-a-spatial-query) +- [Full-text search](../../../client-api/session/querying/text-search/full-text-search) + +### Indexes + +- [Sort index query results](../../../indexes/querying/sorting) diff --git a/Documentation/6.0/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php b/Documentation/6.0/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php new file mode 100644 index 0000000000..9ad9c7de26 --- /dev/null +++ b/Documentation/6.0/Samples/php/ClientApi/session/Querying/HowToProjectQueryResults.php @@ -0,0 +1,241 @@ +openSession(); + try { + # region projections_1 + // request name, city and country for all entities from 'Companies' collection + $queryData = new QueryData( + [ "Name", "Address.city", "Address.country"], + [ "Name", "City", "Country"] + ); + + /** @var array $results */ + $results = $session + ->query(Company::class) + ->selectFields(NameCityAndCountry::class, $queryData) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_2 + $queryData = new QueryData( + [ "ShipTo", "Lines[].ProductName" ], + [ "ShipTo", "Products" ] + ); + + /** @var array $results */ + $results = $session->query(Order::class) + ->selectFields(ShipToAndProducts::class, $queryData) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_3 + /** @var array $results */ + $results = $session->advanced()->rawQuery(FullName::class, "from Employees as e " . + "select {" . + " FullName : e.FirstName + \" \" + e.LastName " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_4 + /** @var array $results */ + $results = $session->advanced()->rawQuery(Total::class, "from Orders as o " . + "select { " . + " Total : o.Lines.reduce( " . + " (acc , l) => acc += l.PricePerUnit * l.Quantity, 0) " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_5 + /** @var array $results */ + $results = $session->advanced()->rawQuery(OrderProjection::class, "from Orders as o " . + "load o.Company as c " . + "select { " . + " CompanyName: c.Name," . + " ShippedAt: o.ShippedAt" . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_6 + /** @var array $results */ + $results = $session->advanced()->rawQuery(EmployeeProjection::class, "from Employees as e " . + "select { " . + " DayOfBirth : new Date(Date.parse(e.Birthday)).getDate(), " . + " MonthOfBirth : new Date(Date.parse(e.Birthday)).getMonth() + 1, " . + " Age : new Date().getFullYear() - new Date(Date.parse(e.Birthday)).getFullYear() " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_7 + /** @var array $results */ + $results = $session->advanced()->rawQuery(EmployeeProjection::class, "from Employees as e " . + "select { " . + " Date : new Date(Date.parse(e.Birthday)), " . + " Name : e.FirstName.substr(0,3) " . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_8 + /** @var array $results */ + $results = $session->query(Company::class, Companies_ByContact::class) + ->selectFields(ContactDetails::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_10 + // query index 'Products_BySupplierName' + // return documents from collection 'Products' that have a supplier 'Norske Meierier' + // project them to 'Products' + /** @var array $results */ + $results = $session->query(Products_BySupplierName_Result::class, Products_BySupplierName::class) + ->whereEquals("Name", "Norske Meierier") + ->ofType(Product::class) + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_12 + /** @var array $results */ + $results = $session->advanced()->rawQuery(Employee::class, "declare function output(e) { " . + " var format = function(p){ return p.FirstName + \" \" + p.LastName; }; " . + " return { FullName : format(e) }; " . + "} " . + "from Employees as e select output(e)") + ->toList(); + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region projections_13 + /** @var array $results */ + $results = $session->advanced()->rawQuery(Employee::class, "from Employees as e " . + "select {" . + " Name : e.FirstName, " . + " Metadata : getMetadata(e)" . + "}") + ->toList(); + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +# region projections_9_0 +class Companies_ByContact extends AbstractIndexCreationTask +{ + public function __construct() + { + parent::__construct(); + + $this->map = "from c in docs.Companies select new { Name = c.Contact.Name, Phone = c.Phone } "; + + $this->storeAllFields(FieldStorage::yes()); // name and phone fields can be retrieved directly from index + } +} +# endregion + +# region projections_9_1 +class ContactDetails +{ + private ?string $name = null; + private ?string $phone = null; + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): void + { + $this->name = $name; + } + + public function getPhone(): ?string + { + return $this->phone; + } + + public function setPhone(?string $phone): void + { + $this->phone = $phone; + } +} +# endregion + +# region projections_11 +class Products_BySupplierName extends AbstractIndexCreationTask +{ +} + +class Products_BySupplierName_Result +{ +} +# endregion diff --git a/Documentation/6.0/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php b/Documentation/6.0/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php new file mode 100644 index 0000000000..1f2a8a4e55 --- /dev/null +++ b/Documentation/6.0/Samples/php/ClientApi/session/Querying/MakeSpatialQuery.php @@ -0,0 +1,196 @@ +openSession(); + try { + //region spatial_4 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->withinRadius(10, 32.1234, 23.4321); } + ) + ->toList(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region spatial_5 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + // this equals to WithinRadius(10, 32.1234, 23.4321) + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->relatesToShape("Circle(32.1234 23.4321 d=10.0000)", SpatialRelation::within()); } + ) + ->toList(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region spatial_7 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + // sort results by distance from 32.1234 latitude and 23.4321 longitude point + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->withinRadius(10, 32.1234, 23.4321); } + ) + ->orderByDistance( + new PointField("latitude", "longtude"), + 32.12324, 23.4321) + ->toList(); + //endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + //region spatial_9 + // return all matching entities + // within 10 kilometers radius + // from 32.1234 latitude and 23.4321 longitude coordinates + // sort results by distance from 32.1234 latitude and 23.4321 longitude point + /** @var array $results */ + $results = $session + ->query(House::class) + ->spatial( + new PointField("latitude", "longitude"), + function($f) { $f->withinRadius(10, 32.1234, 23.4321); } + ) + ->orderByDistanceDescending( + new PointField("latitude", "longtude"), + 32.12324, 23.4321) + ->toList(); + //endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +} + +class House { + private ?string $name = null; + private ?float $latitude = null; + private ?float $longitude = null; + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): void + { + $this->name = $name; + } + + public function getLatitude(): ?float + { + return $this->latitude; + } + + public function setLatitude(?float $latitude): void + { + $this->latitude = $latitude; + } + + public function getLongitude(): ?float + { + return $this->longitude; + } + + public function setLongitude(?float $longitude): void + { + $this->longitude = $longitude; + } +} \ No newline at end of file diff --git a/Documentation/6.0/Samples/php/ClientApi/session/Querying/SortQueryResults.php b/Documentation/6.0/Samples/php/ClientApi/session/Querying/SortQueryResults.php new file mode 100644 index 0000000000..47ec58502f --- /dev/null +++ b/Documentation/6.0/Samples/php/ClientApi/session/Querying/SortQueryResults.php @@ -0,0 +1,440 @@ +openSession(); + try { + // Order by document field + // ======================= + + # region sort_1 + /** @var array $products */ + $products = $session + // Make a dynamic query on the Products collection + ->query(Product::class) + // Apply filtering (optional) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'OrderBy', pass the document-field by which to order the results + ->orderBy("UnitsInStock") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value in ascending order, + // with smaller values listed first. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_3 + /** @var array $products */ + $products = $session->advanced() + // Make a DocumentQuery on the Products collection + ->documentQuery(Product::class) + // Apply filtering (optional) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'OrderBy', pass the document-field by which to order the results + ->orderBy("UnitsInStock") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value in ascending order, + // with smaller values listed first. + # endregion + } finally { + $session->close(); + } + + // Order by score + // ============== + + $session = $store->openSession(); + try { + # region sort_4 + /** @var array $products */ + $products = $session + ->query(Product::class) + // Apply filtering + ->whereLessThan("UnitsInStock", 5) + ->orElse() + ->whereEquals("Discontinued", true) + // Call 'orderByScore' + ->orderByScore() + ->toList(); + + // Results will be sorted by the score value + // with best matching documents (higher score values) listed first. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_6 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + // Apply filtering + ->whereLessThan("UnitsInStock", 5) + ->orElse() + ->whereEquals("Discontinued", true) + // Call 'orderByScore' + ->orderByScore() + ->toList(); + + // Results will be sorted by the score value + // with best matching documents (higher score values) listed first. + # endregion + } finally { + $session->close(); + } + + // Order by random + // =============== + + $session = $store->openSession(); + try { + # region sort_7 + /** @var array $products */ + $products = $session->query(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'randomOrdering' + ->randomOrdering() + // An optional seed can be passed, e.g.: + // ->randomOrdering('someSeed') + ->toList(); + + // Results will be randomly ordered. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_9 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Call 'randomOrdering' + ->randomOrdering() + // An optional seed can be passed, e.g.: + // ->randomOrdering('someSeed') + ->toList(); + + // Results will be randomly ordered. + # endregion + } finally { + $session->close(); + } + + // Order by Count + // ============== + + $session = $store->openSession(); + try { + # region sort_10 + $numberOfProductsPerCategory = $session + ->query(Product::class) + // Make an aggregation query + ->groupBy("Category") + ->selectKey("Category") + // Count the number of product documents per category + ->selectCount() + // Order by the Count value + // Here you need to specify the ordering type explicitly + ->orderBy("Count", OrderingType::long()) + ->toList(); + + // Results will contain the number of Product documents per category + // ordered by that count in ascending order. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_12 + $numberOfProductsPerCategory = $session->advanced() + ->documentQuery(Product::class) + // Group by Category + ->groupBy("Category") + ->selectKey("Category") + // Count the number of product documents per category + ->selectCount() + // Order by the Count value + // Here you need to specify the ordering type explicitly + ->orderBy("Count", OrderingType::long()) + ->toList(); + + // Results will contain the number of Product documents per category + // ordered by that count in ascending order. + # endregion + } finally { + $session->close(); + } + + // Order by Sum + // ============ + + $session = $store->openSession(); + try { + # region sort_13 + $numberOfUnitsInStockPerCategory = $session + ->query(Product::class) + // Make an aggregation query + // Group by Category + ->groupBy("Category") + // Order by the Sum value + ->selectKey("Category") + ->selectSum(new GroupByField("UnitsInStock", "Sum")) + ->orderBy("Sum") + ->toList(); + + // Results will contain the total number of units in stock per category + // ordered by that number in ascending order. + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_15 + $numberOfUnitsInStockPerCategory = $session->advanced() + ->documentQuery(Product::class) + // Group by Category + ->groupBy("Category") + ->selectKey("Category") + // Sum the number of units in stock per category + ->selectSum(new GroupByField("UnitsInStock", "Sum")) + // Order by the Sum value + // Here you need to specify the ordering type explicitly + ->orderBy("Sum", OrderingType::long()) + ->toList(); + + // Results will contain the total number of units in stock per category + // ordered by that number in ascending order. + # endregion + } finally { + $session->close(); + } + + // Force ordering type + // =================== + + $session = $store->openSession(); + try { + # region sort_16 + /** @var array $products */ + $products = $session + ->query(Product::class) + // Call 'OrderBy', order by field 'QuantityPerUnit' + // Pass a second param, requesting to order the text alphanumerically + ->orderBy("QuantityPerUnit", OrderingType::alphaNumeric()) + ->toList(); + # endregion + + # region sort_16_results + // Running the above query on the NorthWind sample data, + // would produce the following order for the QuantityPerUnit field: + // ================================================================ + + // "1 kg pkg." + // "1k pkg." + // "2 kg box." + // "4 - 450 g glasses" + // "5 kg pkg." + // ... + + // While running with the default Lexicographical ordering would have produced: + // ============================================================================ + + // "1 kg pkg." + // "10 - 200 g glasses" + // "10 - 4 oz boxes" + // "10 - 500 g pkgs." + // "10 - 500 g pkgs." + // ... + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_18 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + // Call 'OrderBy', order by field 'QuantityPerUnit' + // Pass a second param, requesting to order the text alphanumerically + ->orderBy("QuantityPerUnit", OrderingType::alphaNumeric()) + ->toList(); + # endregion + } finally { + $session->close(); + } + + // Chain ordering + // ============== + + $session = $store->openSession(); + try { + # region sort_19 + /** @var array $products */ + $products = $session + ->query(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Apply the primary sort by 'UnitsInStock' + ->orderByDescending("UnitsInStock") + // Apply a secondary sort by the score (for products with the same # of units in stock) + ->orderByScore() + // Apply another sort by 'Name' (for products with same # of units in stock and same score) + ->orderBy("Name") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value (descending), + // then by score, + // and then by 'Name' (ascending). + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_21 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Apply the primary sort by 'UnitsInStock' + ->orderByDescending("UnitsInStock") + // Apply a secondary sort by the score + ->orderByScore() + // Apply another sort by 'Name' + ->orderBy("Name") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value (descending), + // then by score, + // and then by 'Name' (ascending). + # endregion + } finally { + $session->close(); + } + + // Custom sorters + // ============== + + $session = $store->openSession(); + try { + # region sort_22 + /** @var array $products */ + $products = $session + ->query(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Order by field 'UnitsInStock', pass the name of your custom sorter class + ->orderBy("UnitsInStock", "MySorter") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value + // according to the logic from 'MySorter' class + # endregion + } finally { + $session->close(); + } + + $session = $store->openSession(); + try { + # region sort_24 + /** @var array $products */ + $products = $session->advanced() + ->documentQuery(Product::class) + ->whereGreaterThan("UnitsInStock", 10) + // Order by field 'UnitsInStock', pass the name of your custom sorter class + ->orderBy("UnitsInStock", "MySorter") + ->toList(); + + // Results will be sorted by the 'UnitsInStock' value + // according to the logic from 'MySorter' class + # endregion + } finally { + $session->close(); + } + + // Get score from metadata + // ======================= + + $session = $store->openSession(); + try { + # region get_score_from_metadata + // Make a query: + // ============= + + $employees = $session + ->query(Employee::class) + ->search("Notes", "English") + ->search("Notes", "Italian") + ->boost(10) + ->toList(); + + // Get the score: + // ============== + + // Call 'GetMetadataFor', pass an entity from the resulting employees list + $metadata = $session->advanced()->getMetadataFor($employees[0]); + + // Score is available in the 'INDEX_SCORE' metadata property + $score = $metadata[DocumentsMetadata::INDEX_SCORE]; + # endregion + } finally { + $session->close(); + } + } finally { + $store->close(); + } + } +}