Re: Filters as views (ISSUE-45)

Hi Asbjørn

Finally I had time to craft few examples of what I've implemented.

>> Client side have several components which are checked against each 
>> mapping
>> and if it responds positively it is allowed to process passed information
>> (current filter settings, paging, etc.) and generates an expression. This
>> way I can have several components which may "understand" various 
>> mappings.
>> If no components is applicable, it is just left untouched. Iri template
>> allows the value to be optional, thus it will miss that very variable 
>> value.
>Could you please post examples of how this looks on the wiki so it can
>be discussed further and so people understand just exactly how OData
>can be used in Hydra? I think that's unclear for a lot of people,
>perhaps me included. :-)

Consider an API entry point that generates an API documentation containing 
the snipped below (in Turtle, it's sooo much shorter than JSON-LD):

@PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@PREFIX hydra: <http://www.w3.org/ns/hydra/core#> .
@BASE <http://temp.uri/api/person/> .
<LIST#withTemplate> a hydra:TemplatedLink;
    hydra:supportedOperation <#LIST> .
<#LIST> a hydra:Operation;
    rdfs:label "List";
    hydra:method "GET";
    hydra:returns [ a hydra:Collection ] .
<LIST#template> a hydra:IriTemplate;
    hydra:template "/api/person{?$skip,$top,$filter}";
    hydra:mapping [
        hydra:property <http://docs.oasis-open.org/odata/odata/v4.0/$skip>;
        hydra:variable "$skip"
    ], [
        hydra:property <http://docs.oasis-open.org/odata/odata/v4.0/$top>;
        hydra:variable "$top"
    ], [
        hydra:property 
<http://docs.oasis-open.org/odata/odata/v4.0/$filter>;
        hydra:variable "$filter"
    ] .
<http://docs.oasis-open.org/odata/odata/v4.0/$skip> rdfs:range 
<http://www.w3.org/2001/XMLSchema#int> .
<http://docs.oasis-open.org/odata/odata/v4.0/$top> rdfs:range 
<http://www.w3.org/2001/XMLSchema#int> .
<http://docs.oasis-open.org/odata/odata/v4.0/$filter> rdfs:range 
<http://www.w3.org/2001/XMLSchema#string> .

Now when client figures it out that there is a GET operation that returns a 
hydra:Collection it will find out the IRI template with three mappings.
The client is designed so it is possible to plug custom component 
implementations that will be asked for each of the mapping in the template 
whether it is capable of processing it.
If so, it is passed an object that has current UI filter states, including 
current page and page size, i.e. (in JSON):
{
    "http://schema.org/givenName": "karol",
    "http://schema.org/familyName": "s",
    "currentPage": 1,
    "pageSize: 10
}

The OData component would respond positively for all of the three mappings 
as it understands mapped properties. While processing passed instance, the 
instance would be transformed into an actual object passed to the IRI 
template processor. Based on the API description it would know that 
"currentPage" (a generic property, unmapped to anything specific) would be 
translated to skip = 0, "pageSize" to top = 10 and other properties would be 
translated into a filter:
{
    "$skip": 0,
    "$top": 10,
    "$filter": "(indexOf(<http://schema.org/givenName>, 'karol') gt -1) and 
(indexOf(<http://schema.org/familyName>, 's') gt -1)"
}

The logic of how to transform properties into a filter sits in that 
component - it is hardcoded how and when to use indexOf or eq(Equal) or gt 
(Greater Than).
If no component is available that would transform the filters into a 
variable, it would be omitted as the template allows it leaving space for 
uncertainty.

>> I could use 
>> http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part2-url-conventions/odata-v4.0-errata02-os-part2-url-conventions-complete.html#_Toc406398094
>> as the reference, which is actual one leading to $filter description, but 
>> it
>> looks ugly.
>Indeed. How about defining an alias in purl.org and using the purl alias 
>instead?
I have poor experiences with purl.org - it failed me several times :(. But 
still, having an alias would an option.

>I agree, which is why I'd really appreciate if Karol could contribute his 
>OData implementation on the wiki.
I hesitated to put this example on the Collections Interaction Flow as it 
seems quite complex and somehow doesn't fit there - if you have any idea on 
where to put it give me a shout!

>> EQUALS is not enough for everything; but it is a good default.
>> The mechanism should be extensible (for instance, freeTextQuery).
Equals is not good as default as well. It would work for integer numbers, 
but starts to fail for floats and dates. I was implementing this logic in my 
URSA client for OData and it contains quite a logic! I.e., for dates 
different filter is generated when a full date/time is provided, different 
when only date and time rounded to hours.

>I think it's unwise for Hydra to have any querying capability at all
>built in. Instead, it should be really easy to plug in OData, SPARQL
>and other extrenal query langauges. Anything we try to specify in
>Hydra is not going to be sufficient for anything but the simplest and
>most banal cases and I'd argue won't be anywhere near the 80/20 rule
>that often governs decisions on whether to include something like this
>in a specification or not.
I think I'm keen to agree with that. Querying is a huge topic and having 
some prothesis would do more harm than good. Tomasz's idea of pluggable 
vocabs seems more reasonable.

I'm almost done with fooling aroung with my code, thus I should be able to 
push the updated demo with filters to the live site. Code is already 
available on the github.

BTW. Recently I revisited HTTP RFC and it reminded me of a HTTP 206 Partial 
Content and Content-Range header. Isn't it a preferred solution of HTTP 
understanding ReST API client implementation for paging?

Best

Karol 

Received on Sunday, 28 February 2016 21:25:04 UTC