Querying an Index
-
Prior to this article, it is recommended that you first read this Query Overview.
-
For a basic indexes overview, see the Indexes Overview.
-
Indexing the content of your documents allows for fast document retrieval when querying the index.
-
This article is a basic overview of how to query a static index using code.
- For dynamic query examples see Query Overview.
- An index can also be queried from Studio using RQL.
-
Querying can be enhanced using these extension methods.
-
In this page:
Query index - no filtering
// Query the 'Employees' collection using the index - without filtering
// (Open the 'Index' tab to view the index class definition)
/** @var array<Employee> $employees */
$employees = $session
// Pass the queried collection as the first generic parameter
// Pass the index class as the second generic parameter
->query(Employee::class, Employees_ByName::class)
// Execute the query
->toList();
// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned
// Query the 'Employees' collection using the index - without filtering
/** @var array<Employee> $employees */
$employees = $session
// Pass the index name as a parameter
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
->query(Employee::class, "Employees/ByName")
// Execute the query
->toList();
// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned
// The IndexEntry class defines the index-fields
class Employees_ByName_IndexEntry
{
private ?string $firstName = null;
private ?string $lastName = null;
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): void
{
$this->firstName = $firstName;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): void
{
$this->lastName = $lastName;
}
}
// The index definition:
class Employees_ByName extends AbstractIndexCreationTask
{
public function __construct()
{
parent::__construct();
// The 'Map' function defines the content of the INDEX-fields
// * The content of INDEX-fields 'FirstName' & 'LastName'
// is composed of the relevant DOCUMENT-fields.
$this->map = "from e in docs.Employees select new {FirstName = e.FirstName, LastName = e.LastName}";
// * The index-fields can be queried on to fetch matching documents.
// You can query and filter Employee documents based on their first or last names.
// * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
// will Not be indexed.
// * Note: the INDEX-field name does Not have to be exactly the same
// as the DOCUMENT-field name.
}
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
from index "Employees/ByName"
// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned
Query index - with filtering
// Query the 'Employees' collection using the index - filter by INDEX-field
/** @var array<Employee> $employees */
$employees = $session
// Pass the IndexEntry class as the first generic parameter
// Pass the index class as the second generic parameter
->query(Employees_ByName_IndexEntry::class, Employees_ByName::class)
// Filter the retrieved documents by some predicate on an INDEX-field
->whereEquals("LastName", "King")
// Specify the type of the returned document entities
->ofType(Employee::class)
// Execute the query
->toList();
// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// The IndexEntry class defines the index-fields
class Employees_ByName_IndexEntry
{
private ?string $firstName = null;
private ?string $lastName = null;
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): void
{
$this->firstName = $firstName;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): void
{
$this->lastName = $lastName;
}
}
// The index definition:
class Employees_ByName extends AbstractIndexCreationTask
{
public function __construct()
{
parent::__construct();
// The 'Map' function defines the content of the INDEX-fields
// * The content of INDEX-fields 'FirstName' & 'LastName'
// is composed of the relevant DOCUMENT-fields.
$this->map = "from e in docs.Employees select new {FirstName = e.FirstName, LastName = e.LastName}";
// * The index-fields can be queried on to fetch matching documents.
// You can query and filter Employee documents based on their first or last names.
// * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
// will Not be indexed.
// * Note: the INDEX-field name does Not have to be exactly the same
// as the DOCUMENT-field name.
}
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
from index "Employees/ByName"
where LastName == "King"
// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
-
ofType
is used to convert the type being used in the where clause (IndexEntry
)
to the collection type (Employee
).
The reason for this is that while theIndexEntry
type allows for a strongly typed query,
the server returns the actual documents entities objects. -
An exception will be thrown when filtering by fields that are Not defined in the index.
-
Read more about filtering here.
Query index - with paging
// Query the 'Employees' collection using the index - page results
// This example is based on the previous filtering example
/** @var array<Employee> $employees */
$employees = $session
->query(Employees_ByName_IndexEntry::class, Employees_ByName::class)
->whereEquals("LastName", "King")
->skip(5) // Skip first 5 results
->take(10) // Retrieve up to 10 documents
->ofType(Employee::class)
->toList();
// Results will include up to 10 matching documents
// The IndexEntry class defines the index-fields
class Employees_ByName_IndexEntry
{
private ?string $firstName = null;
private ?string $lastName = null;
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): void
{
$this->firstName = $firstName;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): void
{
$this->lastName = $lastName;
}
}
// The index definition:
class Employees_ByName extends AbstractIndexCreationTask
{
public function __construct()
{
parent::__construct();
// The 'Map' function defines the content of the INDEX-fields
// * The content of INDEX-fields 'FirstName' & 'LastName'
// is composed of the relevant DOCUMENT-fields.
$this->map = "from e in docs.Employees select new {FirstName = e.FirstName, LastName = e.LastName}";
// * The index-fields can be queried on to fetch matching documents.
// You can query and filter Employee documents based on their first or last names.
// * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
// will Not be indexed.
// * Note: the INDEX-field name does Not have to be exactly the same
// as the DOCUMENT-field name.
}
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
from index "Employees/ByName"
where LastName == "King"
limit 5, 10 // skip 5, take 10
- Read more about paging here.
Query an index by documentQuery
// Query the 'Employees' collection using the index - filter by INDEX-field
/** @var array<Employee> $employees */
$employees = $session->advanced()
// Pass the IndexEntry class as the first generic parameter
// Pass the index class as the second generic parameter
->documentQuery(Employees_ByName_IndexEntry::class, Employees_ByName::class)
// Filter the retrieved documents by some predicate on an INDEX-field
->whereEquals("LastName", "King")
// Specify the type of the returned document entities
->ofType(Employee::class)
// Execute the query
->toList();
// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// Query the 'Employees' collection using the index - filter by INDEX-field
/** @var array<Employee> $employees */
$employees = $session->advanced()
// Pass the IndexEntry class as the generic param
// Pass the index name as the param
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
->documentQuery(Employees_ByName_IndexEntry::class, "Employees/ByName")
// Filter the retrieved documents by some predicate on an INDEX-field
->whereEquals("LastName", "King")
// Specify the type of the returned document entities
->ofType(Employee::class)
// Execute the query
->toList();
// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// The IndexEntry class defines the index-fields
class Employees_ByName_IndexEntry
{
private ?string $firstName = null;
private ?string $lastName = null;
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): void
{
$this->firstName = $firstName;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): void
{
$this->lastName = $lastName;
}
}
// The index definition:
class Employees_ByName extends AbstractIndexCreationTask
{
public function __construct()
{
parent::__construct();
// The 'Map' function defines the content of the INDEX-fields
// * The content of INDEX-fields 'FirstName' & 'LastName'
// is composed of the relevant DOCUMENT-fields.
$this->map = "from e in docs.Employees select new {FirstName = e.FirstName, LastName = e.LastName}";
// * The index-fields can be queried on to fetch matching documents.
// You can query and filter Employee documents based on their first or last names.
// * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
// will Not be indexed.
// * Note: the INDEX-field name does Not have to be exactly the same
// as the DOCUMENT-field name.
}
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
from index "Employees/ByName"
where LastName == "King"
Query an index by rawQuery
-
Queries defined with Query or DocumentQuery are translated by the RavenDB client to RQL
when sent to the server. -
The session also gives you a way to express the query directly in RQL using the
session->advanced->rawQuery
method.
Example:
// Query with RawQuery - filter by INDEX-field
/** @var array<Employee> $employees */
$employees = $session->advanced()
// Provide RQL to RawQuery
->rawQuery(Employee::class, "from index 'Employees/ByName' where LastName == 'King'")
// Execute the query
->toList();
// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// The IndexEntry class defines the index-fields
class Employees_ByName_IndexEntry
{
private ?string $firstName = null;
private ?string $lastName = null;
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): void
{
$this->firstName = $firstName;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): void
{
$this->lastName = $lastName;
}
}
// The index definition:
class Employees_ByName extends AbstractIndexCreationTask
{
public function __construct()
{
parent::__construct();
// The 'Map' function defines the content of the INDEX-fields
// * The content of INDEX-fields 'FirstName' & 'LastName'
// is composed of the relevant DOCUMENT-fields.
$this->map = "from e in docs.Employees select new {FirstName = e.FirstName, LastName = e.LastName}";
// * The index-fields can be queried on to fetch matching documents.
// You can query and filter Employee documents based on their first or last names.
// * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
// will Not be indexed.
// * Note: the INDEX-field name does Not have to be exactly the same
// as the DOCUMENT-field name.
}
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition
from index "Employees/ByName"
where LastName == "King"