Customize Query
-
Use
Customize()
to set the following customization options on a specific Query.
Can be set for both dynamic and index queries. -
Each such customization can also be implemented via the DocumentQuery API.
-
A query can also be customized on the Store or Session level by subscribing to
OnBeforeQuery
.
Learn more in Subscribing to Events. -
Customization methods available:
BeforeQueryExecuted
- Use
BeforeQueryExecuted
to customize the query just before it is executed.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'BeforeQueryExecuted'
.Customize(x => x.BeforeQueryExecuted(query =>
{
// Can modify query parameters
query.SkipDuplicateChecking = true;
// Can apply any needed action, e.g. write to log
_logger.Info($"Query to be executed is: {query.Query}");
}))
.Where(x => x.FirstName == "Robert")
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'BeforeQueryExecuted'
.Customize(x => x.BeforeQueryExecuted(query =>
{
// Can modify query parameters
query.SkipDuplicateChecking = true;
// Can apply any needed action, e.g. write to log
_logger.Info($"Query to be executed is: {query.Query}");
}))
.Where(x => x.FirstName == "Robert")
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
.WhereEquals(x => x.FirstName, "Robert")
// Call 'BeforeQueryExecuted'
.BeforeQueryExecuted(query =>
{
// Can modify query parameters
query.SkipDuplicateChecking = true;
// Can apply any needed action, e.g. write to log
_logger.Info($"Query to be executed is: {query.Query}");
})
.ToList();
List<Employee> results = session.Advanced
.RawQuery<Employee>("from 'Employees' where FirstName == 'Robert'")
// Call 'BeforeQueryExecuted'
.BeforeQueryExecuted(query =>
{
// Can modify query parameters
query.SkipDuplicateChecking = true;
// Can apply any needed action, e.g. write to log
_logger.Info($"Query to be executed is: {query.Query}");
})
.ToList();
Syntax
IDocumentQueryCustomization BeforeQueryExecuted(Action<IndexQuery> action);
Parameters | Type | Description |
---|---|---|
action | Action<IndexQuery> |
An Action method that operates on the query. The query is passed in the IndexQuery param. |
AfterQueryExecuted
- Use
AfterQueryExecuted
to access the raw query result after it is executed.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'AfterQueryExecuted'
.Customize(x => x.AfterQueryExecuted(rawResult =>
{
// Can access the raw query result
var queryDuration = rawResult.DurationInMs;
// Can apply any needed action, e.g. write to log
_logger.Info($"{rawResult.LastQueryTime}");
}))
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'AfterQueryExecuted'
.Customize(x => x.AfterQueryExecuted(rawResult =>
{
// Can access the raw query result
var queryDuration = rawResult.DurationInMs;
// Can apply any needed action, e.g. write to log
_logger.Info($"{rawResult.LastQueryTime}");
}))
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
// Call 'AfterQueryExecuted'
.AfterQueryExecuted(rawResult =>
{
// Can access the raw query result
var queryDuration = rawResult.DurationInMs;
// Can apply any needed action, e.g. write to log
_logger.Info($"{rawResult.LastQueryTime}");
})
.ToList();
List<Employee> results = session.Advanced
.RawQuery<Employee>("from 'Employees'")
// Call 'AfterQueryExecuted'
.AfterQueryExecuted(rawResult =>
{
// Can access the raw query result
var queryDuration = rawResult.DurationInMs;
// Can apply any needed action, e.g. write to log
_logger.Info($"{rawResult.LastQueryTime}");
})
.ToList();
Syntax
IDocumentQueryCustomization AfterQueryExecuted(Action<QueryResult> action);
Parameters | Type | Description |
---|---|---|
action | Action<QueryResult> |
An Action method that receives the raw query result. The query result is passed in the QueryResult param. |
AfterStreamExecuted
-
Use
AfterStreamExecuted
to retrieve a raw (blittable) result of the streaming query. -
Learn more in how to stream query results.
Example
long totalStreamedResultsSize = 0;
// Define the query
var query = session
.Query<Employee>()
// Call 'Customize' with 'AfterStreamExecuted'
.Customize(x => x.AfterStreamExecuted(streamResult =>
// Can access the stream result
totalStreamedResultsSize += streamResult.Size));
// Call 'Stream' to execute the query
var streamResults = session.Advanced.Stream(query);
long totalStreamedResultsSize = 0;
// Define the query
var query = asyncSession
.Query<Employee>()
// Call 'Customize' with 'AfterStreamExecuted'
.Customize(x => x.AfterStreamExecuted(streamResult =>
// Can access the stream result
totalStreamedResultsSize += streamResult.Size));
// Call 'Stream' to execute the query
var streamResults = await asyncSession.Advanced.StreamAsync(query);
long totalStreamedResultsSize = 0;
// Define the document query
var query = session.Advanced
.DocumentQuery<Employee>()
// Call 'AfterStreamExecuted'
.AfterStreamExecuted(streamResult =>
// Can access the stream result
totalStreamedResultsSize += streamResult.Size);
// Call 'Stream' to execute the document query
var streamResults = session.Advanced.Stream(query);
long totalStreamedResultsSize = 0;
// Define the raw query
var query = session.Advanced
.RawQuery<Employee>("from 'Employees'")
// Call 'AfterStreamExecuted'
.AfterStreamExecuted(streamResult =>
// Can access the stream result
totalStreamedResultsSize += streamResult.Size);
// Call 'Stream' to execute the document query
var streamResults = session.Advanced.Stream(query);
Syntax
IDocumentQueryCustomization AfterStreamExecuted(Action<BlittableJsonReaderObject> action);
Parameters | Type | Description |
---|---|---|
action | Action<BlittableJsonReaderObject> |
An Action method that recieves a single stream query result. The stream result is passed in the BlittableJsonReaderObject param. |
NoCaching
-
By default, query results are cached.
-
You can use the
NoCaching
customization to disable query caching. -
Learn more in disable caching per session.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'NoCaching'
.Customize(x => x.NoCaching())
.Where(x => x.FirstName == "Robert")
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'NoCaching'
.Customize(x => x.NoCaching())
.Where(x => x.FirstName == "Robert")
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
.WhereEquals(x => x.FirstName, "Robert")
// Call 'NoCaching'
.NoCaching()
.ToList();
List<Employee> results = session.Advanced
.RawQuery<Employee>("from 'Employees' where FirstName == 'Robert'")
// Call 'NoCaching'
.NoCaching()
.ToList();
Syntax
IDocumentQueryCustomization NoCaching();
NoTracking
-
By default, the Session 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 for all other options.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'NoTracking'
.Customize(x => x.NoTracking())
.Where(x => x.FirstName == "Robert")
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'NoTracking'
.Customize(x => x.NoTracking())
.Where(x => x.FirstName == "Robert")
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
.WhereEquals(x => x.FirstName, "Robert")
// Call 'NoTracking'
.NoTracking()
.ToList();
List<Employee> results = session.Advanced
.RawQuery<Employee>("from 'Employees' where FirstName == 'Robert'")
// Call 'NoTracking'
.NoTracking()
.ToList();
Syntax
IDocumentQueryCustomization NoTracking();
Projection
-
By default, when querying an 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. -
If the index does Not store those fields then the fields' 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:
Example
List<string> results = session
.Query<Employees_ByFullName.IndexEntry, Employees_ByFullName>()
// Call 'Customize'
// Pass the requested projection behavior to the 'Projection' method
.Customize(x => x.Projection(ProjectionBehavior.FromDocumentOrThrow))
// Select the fields that will be returned by the projection
.Select(x => x.FullName)
.ToList();
List<string> results = await asyncSession
.Query<Employees_ByFullName.IndexEntry, Employees_ByFullName>()
// Call 'Customize'
// Pass the requested projection behavior to the 'Projection' method
.Customize(x => x.Projection(ProjectionBehavior.FromDocumentOrThrow))
// Select the fields that will be returned by the projection
.Select(x => x.FullName)
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>("Employees/ByFullName")
// Pass the requested projection behavior to the 'SelectFields' method
// and specify the field that will be returned by the projection
.SelectFields<Employee>(ProjectionBehavior.FromDocumentOrThrow, "FullName")
.ToList();
List<Employee> results = session.Advanced
// Define an RQL query that returns a projection
.RawQuery<Employee>(@"from index 'Employees/ByFullName' select FullName")
// Pass the requested projection behavior to the 'Projection' method
.Projection(ProjectionBehavior.FromDocumentOrThrow)
.ToList();
public class Employees_ByFullName : AbstractIndexCreationTask<Employee, Employees_ByFullName.IndexEntry>
{
// The IndexEntry class defines the index-fields.
public class IndexEntry
{
public string FullName { get; set; }
}
public Employees_ByFullName()
{
// The 'Map' function defines the content of the index-fields
Map = employees => from employee in employees
select new IndexEntry
{
FullName = $"{employee.FirstName} {employee.LastName}"
};
// Store field 'FullName' in the index
Store(x => x.FullName, FieldStorage.Yes);
}
}
In the above example:
-
Field 'FullName' is stored in the index (see index definition in the rightmost tab).
However, the server will try to fetch the value from the document since the default behavior was modified toFromDocumentOrThrow
. -
An exception will be thrown since an 'Employee' document does not contain the property 'FullName'.
(based on the Northwind sample data).
Syntax
IDocumentQueryCustomization Projection(ProjectionBehavior projectionBehavior);
public enum ProjectionBehavior {
Default,
FromIndex,
FromIndexOrThrow,
FromDocument,
FromDocumentOrThrow
}
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.
RandomOrdering
-
Use
RandomOrdering
to order the query results randomly. -
More ordering options are available in this Sorting article.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'RandomOrdering'
.Customize(x => x.RandomOrdering())
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'RandomOrdering'
.Customize(x => x.RandomOrdering())
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
// Call 'RandomOrdering'
.RandomOrdering()
.ToList();
List<Employee> results = session.Advanced
// Define an RQL query that orders the results randomly
.RawQuery<Employee>("from 'Employees' order by random()")
.ToList();
Syntax
IDocumentQueryCustomization RandomOrdering();
IDocumentQueryCustomization RandomOrdering(string seed);
Parameters | Type | Description |
---|---|---|
seed | string |
Order the search results randomly using this seed. Useful when executing repeated random queries. |
Timings
-
Use
Timings
to get detailed stats of the time spent by the server on each part of the query. -
The timing statistics will be included in the query results.
-
Learn more in how to include query timings.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'Timings'
// Provide an out param for the timings results
.Customize(x => x.Timings(out QueryTimings timings))
.Where(x => x.FirstName == "Robert")
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'Timings'
// Provide an out param for the timings results
.Customize(x => x.Timings(out QueryTimings timings))
.Where(x => x.FirstName == "Robert")
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
.WhereEquals(x => x.FirstName, "Robert")
// Call 'Timings'.
// Provide an out param for the timings results
.Timings(out QueryTimings timings)
.ToList();
List<Employee> results = session.Advanced
.RawQuery<Employee>("from 'Employees' where FirstName == 'Robert'")
// Call 'Timings'.
// Provide an out param for the timings results
.Timings(out QueryTimings timings)
.ToList();
Syntax
IDocumentQueryCustomization Timings(out QueryTimings timings);
Parameters | Type | Description |
---|---|---|
timings | QueryTimings |
An out param that will be filled with the timings results |
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. -
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. -
Note: This feature is Not available when streaming the query results.
Calling WaitForNonStaleResults with a streaming query will throw an exception. -
Learn more about stale results in stale indexes.
Example
List<Employee> results = session
.Query<Employee>()
// Call 'Customize' with 'WaitForNonStaleResults'
.Customize(x => x.WaitForNonStaleResults(TimeSpan.FromSeconds(10)))
.Where(x => x.FirstName == "Robert")
.ToList();
List<Employee> results = await asyncSession
.Query<Employee>()
// Call 'Customize' with 'WaitForNonStaleResults'
.Customize(x => x.WaitForNonStaleResults(TimeSpan.FromSeconds(10)))
.Where(x => x.FirstName == "Robert")
.ToListAsync();
List<Employee> results = session.Advanced
.DocumentQuery<Employee>()
.WhereEquals(x => x.FirstName, "Robert")
// Call 'WaitForNonStaleResults'
.WaitForNonStaleResults(TimeSpan.FromSeconds(10))
.ToList();
List<Employee> results = session.Advanced
.RawQuery<Employee>("from 'Employees' where FirstName == 'Robert'")
// Call 'WaitForNonStaleResults'
.WaitForNonStaleResults(TimeSpan.FromSeconds(10))
.ToList();
Syntax
IDocumentQueryCustomization WaitForNonStaleResults(TimeSpan? waitTimeout);
Parameters | Type | Description |
---|---|---|
waitTimeout | TimeSpan? |
Time to wait for non-stale results. Default is 15 seconds. |
Methods return value
All of the above customization methods return the following:
Query return value |
|
---|---|
IDocumentQueryCustomization | Returns self for easier method chaining. |
DocumentQuery return value |
|
---|---|
IQueryBase | Returns self for easier method chaining. |