Search API¶
You can search for content with the PHP API in two ways.
To do this, you can use the SearchService
or Repository filtering.
SearchService¶
SearchService
enables you to perform search queries using the PHP API.
The service should be injected into the constructor of your command or controller.
SearchService in the Back Office
SearchService
is also used in the Back Office of Ibexa DXP,
in components such as Universal Discovery Widget or Sub-items List.
Performing a search¶
To search through content you need to create a LocationQuery
and provide your search criteria as a series of Criterion objects.
For example, to search for all content of a selected Content Type, use one Criterion,
Criterion\ContentTypeIdentifier
(line 14).
The following command takes the Content Type identifier as an argument and lists all results:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
SearchService::findContentInfo
(line 16)
retrieves ContentInfo
objects of the found Content items.
You can also use SearchService::findContent
to get full Content objects, together with their Field information.
To query for a single result, for example by providing a Content ID,
use the SearchService::findSingle
method:
1 2 3 |
|
Tip
For full list and details of available Search Criteria, see Search Criteria reference.
Search result limit
By default search returns up to 25 results. You can change it by setting a different limit to the query:
1 |
|
Search with query
and filter
¶
You can use two properties of the Query
object to search for content: query
and filter
.
In contrast to filter
, query
has an effect of search scoring (relevancy).
It affects default sorting if no Sort Clause is used.
As such, query
is recommended when the search is based on user input.
The difference between query
and filter
is only relevant when using Solr or Elasticsearch search engine.
With the Legacy search engine both properties will give identical results.
Processing large result sets¶
To process a large result set, use eZ\Publish\API\Repository\Iterator\BatchIterator
.
BatchIterator
divides the results of search or filtering into smaller batches.
This enables iterating over results that are too large to handle due to memory constraints.
BatchIterator
takes one of the available adapters (\eZ\Publish\API\Repository\Iterator\BatchIteratorAdapter
) and optional batch size. For example:
1 2 3 4 5 6 7 |
|
You can also define the batch size by setting $iterator->setBatchSize()
.
The following BatchIterator adapters are available, for both query
and filter
searches:
Adapter | Method |
---|---|
ContentFilteringAdapter |
\eZ\Publish\API\Repository\ContentService::find |
ContentInfoSearchAdapter |
\eZ\Publish\API\Repository\SearchService::findContentInfo |
ContentSearchAdapter |
\eZ\Publish\API\Repository\SearchService::findContent |
LocationFilteringAdapter |
\eZ\Publish\API\Repository\LocationService::find |
LocationSearchAdapter |
\eZ\Publish\API\Repository\SearchService::findLocations |
Repository filtering¶
You can use the ContentService::find(Filter)
method to find Content items or
LocationService::find(Filter)
to find Locations using a defined Filter.
ContentService::find
returns an iterable ContentList
while LocationService::find
returns an iterable LocationList
.
Filtering differs from search. It does not use the SearchService
and is not based on indexed data.
Filter
enables you to configure a query using chained methods to select criteria, sorting, limit and offset.
For example, the following command lists all Content items under the specified parent Location and sorts them by name in descending order:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
The same Filter can be applied to find Locations instead of Content items, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Notice that the total number of items is retrieved differently for ContentList
and LocationList
.
Caution
The total count is the total number of matched items, regardless of pagination settings.
Repository filtering is SiteAccess-aware
Repository filtering is SiteAccess-aware, which means you can skip the second argument of the find
methods.
In that case languages from a current context are injected and added as a LanguageCode Criterion filter.
You can use the following methods of the Filter:
withCriterion
- add the first Criterion to the FilterandWithCriterion
- add another Criterion to the Filter using a LogicalAnd operation. If this is the first Criterion, this method works likewithCriterion
orWithCriterion
- add a Criterion using a LogicalOr operation. If this is the first Criterion, this method works likewithCriterion
withSortClause
- add a Sort Clause to the FiltersliceBy
- set limit and offset for paginationreset
- remove all Criteria, Sort Clauses, and pagination settings
The following example filters for Folder Content items under the parent Location 2, sorts them by publication date and returns 10 results, starting from the third one:
1 2 3 4 5 6 |
|
Search Criteria and Sort Clause availability
Not all Search Criteria and Sort Clauses are available for use in Repository filtering.
Only Criteria implementing FilteringCriterion
and Sort Clauses implementing FilteringSortClause
are supported.
See Search Criteria and Sort Clause reference for details.
Tip
It is recommended to use an IDE that can recognize type hints when working with Repository Filtering. If you try to use an unsupported Criterion or Sort Clause, the IDE will indicate an issue.
Searching in a controller¶
You can use the SearchService
or Repository filtering in a controller, as long as you provide the required parameters.
For example, in the code below, locationId
is provided to list all children of a Location by using the SearchService
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
The rendering of results is then relegated to templates (lines 20-22).
When using Repository filtering, provide the results of ContentService::find()
as parameters to the view:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Paginating search results¶
To paginate search or filtering results, it is recommended to use the Pagerfanta library and Ibexa DXP's adapters for it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Pagination can then be rendered for example using the following template:
1 2 3 4 5 6 7 |
|
For more information and examples, see PagerFanta documentation.
Additional search result data¶
You can access the following additional search result data from PagerFanta:
- Aggregation results
- Max. score
- Computation time
- Timeout flag
1 2 |
|
1 2 |
|
Pagerfanta adapters¶
Adapter class name | Description |
---|---|
ContentSearchAdapter |
Makes a search against passed Query and returns Content objects. |
ContentSearchHitAdapter |
Makes a search against passed Query and returns SearchHit objects instead. |
LocationSearchAdapter |
Makes a Location search against passed Query and returns Location objects. |
LocationSearchHitAdapter |
Makes a Location search against passed Query and returns SearchHit objects instead. |
ContentFilteringAdapter |
Applies a Content filter and returns a ContentList object. |
LocationFilteringAdapter |
Applies a Location filter and returns a LocationList object. |
Complex search¶
For more complex searches, you need to combine multiple Criteria.
You can do it using logical operators: LogicalAnd
, LogicalOr
, and LogicalNot
.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
This example takes three parameters from a command — $text
, $contentTypeId
, and $locationId
.
It then combines them using Criterion\LogicalAnd
to search for Content items
that belong to a specific subtree, have the chosen Content Type and contain the provided text (lines 6-8).
This also shows that you can get the total number of search results using the totalCount
property of search results (line 11).
You can also nest different operators to construct more complex queries.
The example below uses the LogicalNot
operator to search for all content containing a given phrase
that does not belong to the provided Section:
1 2 3 4 5 |
|
Combining independent Criteria¶
Criteria are independent of one another. This can lead to unexpected behavior, for instance because content can have multiple Locations.
For example, a Content item has two Locations: visible Location A and hidden Location B. You perform the following query:
1 2 3 4 |
|
The query searches for Location B using the LocationId
Criterion,
and for visible content using the Visibility
Criterion.
Even though the Location B is hidden, the query will find the content because both conditions are satisfied:
- the Content item has Location B
- the Content item is visible (it has the visible Location A)
Sorting results¶
To sort the results of a query, use one of more Sort Clauses.
For example, to order search results by their publicationg date, from oldest to newest, and then alphabetically by content name, add the following Sort Clauses to the query:
1 2 3 |
|
Tip
For the full list and details of available Sort Clauses, see Sort Clause reference.
Searching in trash¶
In the user interface, on the Trash screen, you can search for Content items, and then sort the results based on different criteria.
To search the trash with the API, use the TrashService::findInTrash
method to submit a query for Content items that are held in trash.
Searching in trash supports a limited set of Criteria and Sort Clauses.
For a list of supported Criteria and Sort Clauses, see Search in trash reference.
Note
Searching through the trashed Content items operates directly on the database, therefore you cannot use external search engines, such as Solr or Elasticsearch, and it is impossible to reindex the data.
1 2 3 4 5 6 7 |
|
Caution
Make sure that you set the Criterion on the filter
property.
It is impossible to use the query
property, because the search in trash operation filters the database instead of querying.
Aggregation¶
Feature support
Aggregation is only available in the Solr and Elasticsearch search engines.
With aggregations you can find the count of search results or other result information for each Aggregation type.
To do this, you use of the query's $aggregations
property:
1 |
|
The name of the aggregation must be unique in the given query.
Access the results by using the get()
method of the aggregation:
1 |
|
Aggregation results contain the name of the result and the count of found items:
1 2 3 |
|
With field aggregations you can group search results according to the value of a specific Field. In this case the aggregation takes the Content Type identifier and the Field identifier as parameters.
The following example creates an aggregation named selection
that groups results
according to the value of the topic
Field in the article
Content Type:
1 |
|
With term aggregation you can define additional limits to the results. The following example limits the number of terms returned to 5 and only considers terms that have 10 or more results:
1 2 |
|
To use a range aggregation, you must provide a ranges
array containing a set of Range
objects
that define the borders of the specific range sets.
1 2 3 4 5 6 |
|
Note
The beginning of the range is included and the end is excluded,
so a range between 1 and 30 will include value 1
, but not 30
.
null
means that a range does not have an end.
In the example all values above (and including) 60 are included in the last range.
See Agrregation reference for details of all available aggregations.