As an application user I want to be able to quickly search through my events So I find events I'm interested in.
As an API consumer I want to be able to search through a collection of resources So I can find those interesting to me.
const collection = await hydraClient.getResource("http://example.com/api/events");
const search = colletion
.hypermedia
.links
.withRelationOf("http://http://www.w3.org/ns/hydra/core#search")
.withTemplate()
.first();
if (!!search) {
const query = search.expandTarget(_ =>
_.withProperty("http://http://www.w3.org/ns/hydra/core#freetextQuery")
.havingValueOf("some text"));
const data = await hydraClient.getResource(query);
for (const member of data.members) {
// do something with the _member_, i.e. display it
}
}
The application should be able to search through events, so the user can narrow down the number and importance of the events displayed. This would be simple search scenario without diving into how the search phrase is interpreted by the server and how it is used while searching. Communication would look like this:
GET /api/events
HTTP 200 OK
{
"@context": "/api/context.jsonld",
"@id": "/api/events",
"@type": "Collection",
"manages": {
"property": "rdf:type",
"object": "schema:Event"
},
"totalItems": 1,
"members": [
{
"@id": "/api/events/1",
"eventName": "Event 1",
"eventDescription": "Some event 1",
"startDate": "2017-04-19",
"endDate": "2017-04-19"
}
],
"search": {
"@type": "IriTemplate",
"template": "http://example.com/api/events{?search}",
"variableRepresentation": "BasicRepresentation",
"mapping": [
{
"@type": "IriTemplateMapping",
"variable": "search",
"property": "freetextQuery",
"required": true
}
]
}
}
GET /api/events?search=some%20text
HTTP 200 OK
{
"@context": "/api/context.jsonld",
"@id": "/api/events?search=some text",
"@type": "Collection",
"totalItems": 1,
"members": [
{
"@id": "/api/events/1",
"eventName": "Event 1",
"eventDescription": "Some event having a search phrase",
"startDate": "2017-04-19",
"endDate": "2017-04-19"
}
]
}
There are two main sources of that information which can enable client with a search feature:
- API documentation
- hypermedia controls
Unfortunately, current specification does not clearly state, how the templated link should be embedded in the payload of both. There is an example of a templated link using a special purpose freetextQuery property that can be used for search. There is also a special purpose templated link search, but again it is unclear on how it should be used. Possible payload for hypermedia control would look like this:
GET /api/events
HTTP 200 OK
{
"@context": "/api/context.jsonld",
"@id": "/api/events",
"totalItems": 1,
"members": [
{
"@id": "/api/events/1",
"eventName": "Event 1",
"eventDescription": "Some event 1",
"startDate": "2017-04-19",
"endDate": "2017-04-19"
}
],
"search": {
"@type": "IriTemplate",
"template": "http://example.com/api/events{?search}",
"variableRepresentation": "BasicRepresentation",
"mapping": [
{
"@type": "IriTemplateMapping",
"variable": "search",
"property": "freetextQuery",
"required": true
}
]
}
}
Following analogy of other predefined links, like first for collections, templated links should be used as predicates:
</api/events> search </api-doc/events#search-iri-template> .
The example above of a triple with a templated link seems inconvenient as in order to define a custom templated link, one should create a separate resource. IRI of that resource shall be nicely foldable to QIri form in order to improve readability, resulting in a number of fake namespaces.
Also a location of the template itself within the graph is not clear. The example above puts it as a related resource of the search predicate, but only to fill the gap as there is no other resource that could be used to build up a valid statement. Also this seems compliant (again by analogy) to simple scenario with first predicate, where the related resource is another collection page.