Skip to content

Commit

Permalink
RDoc-2245 [Node.js] Projection articles - Part 4
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielle9897 committed Dec 5, 2023
1 parent 8b99c62 commit 3af9330
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

* [Projection behavior with a static-index](../../indexes/querying/projections#projection-behavior-with-a-static-index)

* [OfType (As)](../../indexes/querying/projections#oftype-(as))
* [OfType](../../indexes/querying/projections#oftype)

{NOTE/}

Expand All @@ -40,10 +40,19 @@ select FirstName as EmployeeFirstName, LastName as EmployeeLastName
{CODE-TAB-BLOCK/}
{CODE-TABS/}

* Since the index-fields in this example are not [Stored in the index](../../indexes/storing-data-in-index), and no projection behavior was defined,
resulting values for `FirstName` & `LastName` will be retrieved from the matching Employee document in the storage.
* __Type of projection fields__:

* In the above example, the fields to return by the projection that are specified in the `Select` method
(`x.FirstName` & `x.LastName`) are recognized by the compiler as fields of the `IndexEntry` class.

* This behavior can be modified by setting the [projection behavior](../../indexes/querying/projections#projection-behavior-with-a-static-index) used when querying a static-index.
* If you wish to specify fields from the original 'Employee' class type then follow [this example](../../indexes/querying/projections#oftype) that uses `OfType`.

* __Source of projection fields__:

* Since the index-fields in this example are not [Stored in the index](../../indexes/storing-data-in-index), and no projection behavior was defined,
resulting values for `FirstName` & `LastName` will be retrieved from the matching Employee document in the storage.

* This behavior can be modified by setting the [projection behavior](../../indexes/querying/projections#projection-behavior-with-a-static-index) used when querying a static-index.

{NOTE/}

Expand Down Expand Up @@ -375,27 +384,36 @@ __Syntax for projection behavior__:

{PANEL/}

{PANEL: OfType (As)}
{PANEL: OfType}

* __Projection queries__:
When querying an index with a projection (as described in this article),
the server searches for documents that match the query predicate, but the returned objects follow the shape of the specified projection - they are not the actual documents.
* When making a projection query, converting the shape of the matching documents to the requested projection is done on the __server-side__.

* On the other hand, `OfType` is a __client-side__ type conversion that is only used to map the resulting objects to the provided type.

* We differentiate between the following cases:
* Using _OfType_ with projection queries - resulting objects are Not tracked by the session
* Using _OfType_ with non-projection queries - resulting documents are tracked by the session

{NOTE: }

* __Non-Projection queries__:
When querying an index without using a projection, the server returns the actual documents that match the query conditions.
However, when filtering such a query by the index-entry fields, a type conversion is required for the compiler to understand the resulting objects' shape.
This is where _OfType_ (or _As_) comes into play.
__Using OfType with projection queries__:

* __Role of `OfType` (or `As`)__:
So this is just a client-side type conversion used to map the query results to the document type.
It ensures the compiler recognizes that the resulting objects conform to the expected document shape.
{CODE-TABS}
{CODE-TAB:csharp:Query projections_15@Indexes\Querying\Projections.cs /}
{CODE-TAB:csharp:Query_async projections_15_async@Indexes\Querying\Projections.cs /}
{CODE-TAB:csharp:Index index_5@Indexes\Querying\Projections.cs /}
{CODE-TAB-BLOCK:sql:RQL}
from index "Companies/ByContactDetailsAndPhone"
where ContactTitle == "owner"
{CODE-TAB-BLOCK/}
{CODE-TABS/}

* __Results are tracked__:
As opposed to projection queries where results are not tracked by the session,
In the case of non-projecting queries that use _OfType_, the session does track the resulting document entities.
{NOTE/}

{NOTE: }

__Using OfType with non-projection queries__:

{CODE-TABS}
{CODE-TAB:csharp:Query projections_14@Indexes\Querying\Projections.cs /}
{CODE-TAB:csharp:Query_async projections_14_async@Indexes\Querying\Projections.cs /}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,27 +510,100 @@ public async Task Examples()
using (var session = store.OpenSession())
{
#region projections_14
// Make a non-projecting query:
// ============================

List<Company> results = session
.Query<Companies_ByContactDetailsAndPhone.IndexEntry, Companies_ByContactDetailsAndPhone>()
// Here we filter by an IndexEntry field,
// Here we filter by an IndexEntry field
// The compiler recognizes 'x' as an IndexEntry type
.Where(x => x.ContactTitle == "owner")
// Here we let the compiler know that results are of type 'Company' documents
// A type conversion is now required for the compiler to understand the resulting objects' shape.
// Use 'OfType to let the compiler know that resulting objects are of type 'Company' documents.
.OfType<Company>()
.ToList();

// The resulting objects are full 'Company' document entities (not projected).
// Each 'Company' entity is TRACKED by the session.
#endregion
}

using (var asyncSession = store.OpenAsyncSession())
{
#region projections_14_async
// Make a non-projecting query:
// ============================

List<Company> results = await asyncSession
.Query<Companies_ByContactDetailsAndPhone.IndexEntry, Companies_ByContactDetailsAndPhone>()
// Here we filter by an IndexEntry field,
// Here we filter by an IndexEntry field
// The compiler recognizes 'x' as an IndexEntry type
.Where(x => x.ContactTitle == "owner")
// Here we let the compiler know that results are of type 'Company' documents
// A type conversion is now required for the compiler to understand the resulting objects' shape.
// Use 'OfType to let the compiler know that resulting objects are of type 'Company' documents.
.OfType<Company>()
.ToListAsync();

// The resulting objects are full 'Company' document entities (not projected).
// Each 'Company' entity is TRACKED by the session.
#endregion
}

using (var session = store.OpenSession())
{
#region projections_15
// Make a projection query:
// ========================

var projectedResults = session
.Query<Companies_ByContactDetailsAndPhone.IndexEntry, Companies_ByContactDetailsAndPhone>()
// Here we filter by an IndexEntry field
// The compiler recognizes 'x' as an IndexEntry type
.Where(x => x.ContactTitle == "owner")
// Now, if you wish to project based on the 'Company' document
// then use 'OfType' to let the compiler recognize the type
.OfType<Company>()
// Select which fields from the matching document will be returned
.Select(x => new
{
// The compiler now recognizes 'x' as a 'Company' class type
// e.g. 'Name' & 'Address.Country' are properties of the 'Company' document
CompanyName = x.Name,
CompanyCountry = x.Address.Country
})
.ToList();

// Each resulting object has the 'CompanyName' & 'CompanyCountry' fields specified in the projection.
// The resulting objects are NOT TRACKED by the session.
#endregion
}

using (var asyncSession = store.OpenAsyncSession())
{
#region projections_15_async
// Make a projection query:
// ========================

var projectedResults = await asyncSession
.Query<Companies_ByContactDetailsAndPhone.IndexEntry, Companies_ByContactDetailsAndPhone>()
// Here we filter by an IndexEntry field
// The compiler recognizes 'x' as an IndexEntry type
.Where(x => x.ContactTitle == "owner")
// Now, if you wish to project based on the 'Company' document
// then use 'OfType' to let the compiler recognize the type
.OfType<Company>()
// Select which fields from the matching document will be returned
.Select(x => new
{
// The compiler now recognizes 'x' as a 'Company' class type
// e.g. 'Name' & 'Address.Country' are properties of the 'Company' document
CompanyName = x.Name,
CompanyCountry = x.Address.Country
})
.ToListAsync();

// Each resulting object has the 'CompanyName' & 'CompanyCountry' fields specified in the projection.
// The resulting objects are NOT TRACKED by the session.
#endregion
}
}
Expand Down

0 comments on commit 3af9330

Please sign in to comment.