Querying: Basics
Indexes are used by RavenDB to satisfy queries.
Query-Flow
Each query in RavenDB must be expressed by RQL, our query language. Each query must match an index in order to return the results. The full query flow is as follows:
-
from index | collection
- First step. When a query is issued, it locates the appropriate index. If our query specifies that index, the task is simple - use this index. Otherwise, a query analysis takes place and an auto-index is created.
-
where
- When we have our index, we scan it for records that match the query predicate.
-
load
- If a query contains a projection that requires any document loads to be processed, they are done just before projection is executed.
-
select
-
From each record, the server extracts the appropriate fields. It always extracts the
id()
field (stored by default). -
If a query is not a projection query, then we load a document from storage. Otherwise, if we stored all requested fields in the index, we use them and continue. If not, the document is loaded from storage and the missing fields are fetched from it.
-
If a query indicates that projection should be used, then all results that were not filtered out are processed by that projection. Fields defined in the projection are extracted from the index (if stored).
-
-
include
- If any includes are defined, then the results are being traversed to extract the IDs of potential documents to include with the results.
-
Return results.
Querying
RavenDB Client supports querying for data. This functionality can be accessed using the session query()
method, and is the most common and basic method for querying the database.
Example I
Let's execute our first query and return all the employees from the Northwind database. To do that, we need to have a document store and opened session and specify a collection type that we want to query (in our case Employees
) by passing Employee
as a first parameter to the query()
method:
// load all entities from 'Employees' collection
const results = await session
.query(Employee)
.all(); // send query
from Employees
By specifying Employee
class as a parameter, we are also defining a result type.
Example II - Filtering
To filter the results, use the suitable method, like whereEquals()
:
// load all entities from 'Employees' collection
// where 'FirstName' is 'Robert'
const results = await session
.query(Employee)
.whereEquals("FirstName", "Robert")
.all(); // send query
from Employees
where firstName = 'Robert'
// load up entity from 'Employees' collection
// with ID matching 'employees/1-A'
const result = await session
.query(Employee)
.whereEquals("Id", "employees/1-A")
.firstOrNull();
from Employees
where id() == 'employees/1-A'
You can read more about filtering here.
Example III - Paging
Paging is very simple. The methods take()
and skip()
can be used:
// load up to 10 entities from 'Products' collection
// where there are more than 10 units in stock
// skip first 5 results
const results = await session
.query(Product)
.whereGreaterThan("UnitsInStock", 10)
.skip(5)
.take(10)
.all(); //send query
You can read more about paging here.
Example IV - Querying a Specified Index
In the above examples, we did not specify an index that we want to query. RavenDB will try to locate an appropriate index or create a new one. You can read more about creating indexes here.
In order to specify an index, we need to pass the index name as a parameter to query()
method.
// load all entities from 'Employees' collection
// where 'FirstName' is 'Robert'
// using 'Employees/ByFirstName' index
const results = await session
.query({ indexName: "Employees/ByFirstName" })
.whereEquals("FirstName", "Robert")
.all(); // send query
from index 'Employees/ByFirstName'
where FirstName = 'Robert'
Remember
If you are filtering by fields that are not present in an index, an exception will be thrown.
Remarks
Information
You can check the API reference for the DocumentQuery
here.