Resource Searching
To help find resources quickly, we have a standard approach in searching records. Some older services may provide their own search mechanisms which will be explained in any specific API guides for that service.
Resource searching can be manually done through software like Postman or even the browser, but the SDKs provide several classes which help build up complex search queries.
Each searchable endpoint will have it's own set of filters available to use.
Filters
Filters are used to narrow down datasets. You can add multiple filters to a query across different fields, or even multiple filters on the same field.
In the API guides, any search endpoints will also list which filters are available. Filters are always structured the same way filters.{field}.{comparison}
.
As a concrete example, if you wanted to find any user with the email address jane.doe@itccompliance.co.uk
, you might use the filter filters.email.equals
.
Each comparison may only be used once for a particular field. So you couldn't have 2 filters.email.equal
filters in the same query.
There are usually alternatives you can use instead. To query multiple values, you can use the in
comparison instead of equals
as an example.
Adding a filter to the query
$query = http_build_query([
'filters' => [
'email' => [
'equals' => 'jane.doe@itccompliance.co.uk',
],
]
]);
Available Comparisons
Comparisons are used to compare the value we want to use in the filter, against what is stored. For example, using an Equals
comparison will do a =
database query, whereas using an In
comparison would use the IN()
query.
The table below details all available comparisons which can be used in queries. Not all endpoints support every comparison. The API guide will explain which comparisons are available for the endpoint.
- Name
after
- Required
- Type
- DateTimeInterface
- Description
Finds records which occurred after a given datetime. Not inclusive.
- Name
after_or_on
- Required
- Type
- DateTimeInterface
- Description
Finds records which occurred after a given datetime. Inclusive.
- Name
before
- Required
- Type
- DateTimeInterface
- Description
Finds records which occurred before a given datetime. Not inclusive.
- Name
before_or_on
- Required
- Type
- DateTimeInterface
- Description
Finds records which occurred before a given datetime. Inclusive.
- Name
between
- Required
- Type
- [<integer|DateTimeInterface>, <integer|DateTimeInterface>]
- Description
Finds records which occur between 2 data points. For example, if searching for ID 3, you can provide
[2, 4]
. Not Inclusive.
- Name
contains
- Required
- Type
- string
- Description
Finds records which contain a string subset. For example, if you wanted to find all records which had the
itccompliance.co.uk
domain name, you could use this comparison.
- Name
doesnt_contain
- Required
- Type
- string
- Description
Same as the contains comparison, but the inverse. To find all records which didn't have the domain
itccompliance.co.uk
, use this filter.
- Name
equals
- Required
- Type
- scalar
- Description
Finds all records which match exactly. This is a loose comparison, stringified numbers are compared equally against integer numbers.
- Name
greater_than
- Required
- Type
- integer
- Description
Similar to the
after
comparison, but for numbers.
- Name
greater_than_or_equal
- Required
- Type
- integer
- Description
Similar to the
after_or_on
comparison, but for numbers.
- Name
in
- Required
- Type
- array
- Description
Provides a way to find a group of records. For example, find records with the ID 1 and 2, you'd use this comparison:
in:[1,2]
.
- Name
inclusive_between
- Required
- Type
- [<integer|DateTimeInterface>, <integer|DateTimeInterface>]
- Description
Similar to the
between
comparison, but inclusive.
- Name
less_than
- Required
- Type
- integer
- Description
Similar to the
before
comparison, but for numbers.
- Name
less_than_or_equal
- Required
- Type
- integer
- Description
Similar to the
before_or_equal
comparison, but for numbers.
- Name
not_equal
- Required
- Type
- scalar
- Description
Similar to the
equal
comparison, but finds records not equal to the value provided.
- Name
not_in
- Required
- Type
- array
- Description
Similar to the
in
comparison, but excludes matching records.
Complex Filter Example
Filters can be continually added to narrow down the data set returned. The code below shows a complex example. Consider we have a user database, and we want to find all dealer type users, which have the domain name itccompliance.co.uk
in the email address, that were created in the year 2022, excluding records with ID 30 and 58, and only records with an ID greater than 20.
Complex Filter Example
use Compliance\Sdk\Search\Search;
use Compliance\Sdk\Search\Filters\GenericFilter;
use Compliance\Sdk\Search\Comparisons\Equals;
use Compliance\Sdk\Search\Comparisons\Contains;
use Compliance\Sdk\Search\Comparisons\Between;
use Compliance\Sdk\Search\Comparisons\NotIn;
use Compliance\Sdk\Search\Comparisons\GreaterThan;
$search = new Search();
$search
->add(new GenericFilter('type', new Equals('dealer'));
->add(new GenericFilter('email', new Contains('itccompliance.co.uk'))
->add(new GenericFilter('created', new Between(
new DateTime('2022-01-01 00:00:00'),
new DateTime('2022-12-31 23:59:59')
))
->add(new GenericFilter('id', new NotIn([30, 58])
->add(new GenericFilter('id', new GreaterThan(20));
As you can see, multiple comparisons can be added to the same field to help narrow down records further. All filters are applied using an AND
condition.
Ordering results
Result sets can be ordered based on field. By default, the resource type being searched will provide a sensible default search order, which is usually the record ID.
You may add multiple sort orders to the query to sort by primary, secondary etc fields.
Sorting example
use Compliance\Sdk\Search\Search;
use Compliance\Sdk\Search\Orders\Order;
$search = new Search();
$search
->order(Order::asc('surname'))
->order(Order::desc('forename'));
Orders will be processed in the order they were provided in. In the example above, because we added the surname asc
order before the forename desc
, results will be ordered by surname ascending first, then forename descending afterwards.
Pagination
The searchable endpoints usually offer several types of pagination, which can be forced through an additional querystring property.
By default, if no result mode is specified, all records will be returned. Obviously this may have a negative effect on some endpoints with large datasets, so please ensure you're paginating where appropriate.
Some specific endpoints will always force a specific result mode type, and ignore any result mode provided in the request. Comments will be added to the API docs where this occurs.
There are 4 different result modes that can be used.
- Name
single
- Required
- Type
- deprecated
- Description
Will return the first record it finds which satisfies the search filters. This result mode is deprecated. You should instead use the
Limited
result mode with a value of1
.
- Name
limited
- Required
- Type
- Description
Will return a limited number of results without pagination data. For example, if you were only interested in the first 10 results, you can use this.
- Name
paginated
- Required
- Type
- Description
Will return a paginated data set. Depending on the type of pagination used (Paged vs Cursor based), it will return additional context to help you navigate to previous / next pages
- Name
all
- Required
- Type
- default
- Description
Will return all records which satisfy the filters. Use carefully.
Pagination examples
use Compliance\Sdk\Search\Search;
use Compliance\Sdk\Search\ResultModes\Single;
$search = new Search();
$search->mode(new Single());