Moving forward with hydra:filter (ISSUE-45)

On 29 Okt 2015 at 22:03, Karol Szczepański wrote:
> On 29 Okt 2015 at 21:45, Ruben Verborgh wrote:
>> On 29 Okt 2015 at 20:40, Karol Szczepański wrote:
>>> Hi Ruben
>>> 
>>> While I'm somehow unhappy to rush with hydra changes to cover particular 
>>> needs in any other specification, TPF in this case,
>>
>> Well, TPF is part of the Hydra family of specs, and the previous change to 
>> the Core Vocabulary spec was breaking. TPF seems to be the most implemented 
>> and thus most affected, so several implementers need to be notified. To 
>> bundle all breaking changes, we need to prioritize this issue, which was 
>> already on the list anyway. I hope this clarifies the timing.
> 
> OK. I expected this kind of answer.

I think Ruben was simply a bit too enthusiastic as we were finally able to solve an issue he raised more than half a year ago. Our (and basically any standardization effort's) process is to first have a discussion. When there seems to be consensus the chair sends out a Call for Consensus to give people that didn't participate in the discussion that far a last chance to raise their objections before an official decision is being made. This process works quite well, so let's try to stick to it. If you have ideas on how to improve the process, please let me know. I'm always open to change things to the better.

Now back to the discussion at hand.


>>>> The hydra:search property is deliberately fuzzy to not restrict its
>>>> usage unnecessarily and thus not always suitable. Sometimes it is
>>>> necessary to filter a collection's members based on the value of their
>>>> properties (not properties of their properties or similar things). To
>>>> enable such use cases, a specialized subproperty of hydra:search named
>>>> hydra:filter would be introduced. The semantics would be that a
>>>> template
>>>> 
>>>>     </collection> hydra:filter [
>>>>       hydra:template "/collection{?first,last}",
>>>>       hydra:mapping [ hydra:variable "first"; hydra:property schema:givenName ],
>>>>       hydra:mapping [ hydra:variable "last"; hydra:property schema:familyName ],
>>>>     ]
>>>> 
>>>> that is expanded to
>>>> 
>>>>     /collection?first=Markus
>>>> 
>>>> would return a collection in which all members correspond to the
>>>> following graph pattern
>>>> 
>>>>     ?member schema:givenName "Markus"
>>>
>>> I'm not sure which fuzziness of the hydra:search you refer to. This
>>
>> Note that these are Markus' words from the issue, not mine. But I
>> agree: hydra:search is defined as selecting items using the given
>> attributes in *some* way. It does not specify how to the server uses
>> the attributes.
>>
>> Instead, hydra:filter states that members should be selected based
>> on whether they have properties that match all attributes. These are
>> stronger semantics than hydra:search.
>
> As I said, this approach implies that all template variables should be 
> treated that way. This disables a case when part of the variables should 
> match property values on the server side and part of the variables should be 
> filled with user input.

Could you please expand on what you mean by that? This is a IRI template so all variables need to be replaced by the client/user input.


> Hypothetical hydra:filter somehow reverses the way 
> the hydra:property is applied in the mapping but it doesn't solve the issue 
> on how to fill the IriTemplate variables with values. Considering your 
> example

[see above]

> The client is informed that the variables first and last will match on the 
> server side properties schema:givenName and schema:familyName respectively.

No, the semantics would be to filter a collection of (presumably) schema:Persons to just return the instances whose schema:givenName and schema:familyName have specific values. In other words, it expresses the following SPARQL query

   SELECT ?member WHERE {
     ?member schema:givenName <"first" value supplied by client> ;
     ?member schema:familyName <"last" value supplied by client> .
   }


> But he doesn't know on where to take the values from to craft the url! In 
> case with hydra:search:
>
> </collection> hydra:search [
>       hydra:template "/collection?search={?search}",
>       hydra:mapping [ hydra:variable "search"; hydra:property 
> hydra:freetextQuery ]
>     ]
>
> my understanding is that client should take a value from the user input. 

The same is true with hydra:filter. One thing that we need to clarify is whether we always want those conditions to be combined by a logical AND or whether we want to allow other functions (OR, NOT) as well. This quickly brings us into complex territory though.



> Taking this by analogy:
> 
> </collection> my:customTemplatedLink [
>       hydra:template "/container/{?name}",
>       hydra:mapping [ hydra:variable "name"; hydra:property 
> schema:givenName ]
>     ]
>
> name value that feeds the template is taken from the resource in context 
> (i.e. PUT operation that updates the resource) or other user input based 
> thingy.

I don't understand what you mean by "resource in context". But it probably also doesn't matter as my:customTemplatedLink could be defined to take the value from anywhere.


> Unless my understanding is incorrect, hydra:filter completely changes that 
> logic but puts disturbance in the force - client doesn't know how to feed 
> the template as the hydra:property doesn't point to the input but to the 
> server side behavior.

No, I think you misunderstood this. We are not trying to parse components of a URL here but try to tell the client how to construct URLs that enable filtering of the collection the hydra:filter property is attached to.


> I'd make it a standalone predicate disconnected from the hydra:search or 
> present a new predicate applicable to the hydra:IriTemplateMapping, i.e.:
> </collection> hydra:search [
>       hydra:template "/collection?first={?first}&last={?last}",
>       hydra:mapping [ hydra:variable "first"; hydra:property 
> hydra:freetextQuery; hydra:filterOnProperty schema:givenName ],
>       hydra:mapping [ hydra:variable "last"; hydra:property 
> hydra:freetextQuery; hydra:filterOnProperty schema:familyName ],
>     ]
> This way you're consistent and fully express what you would like to express.

I think what is being proposed expresses exactly the same but allows a terser serialization. What you the proposal doesn't allow though, is what you express as hydra:property hydra:freetextQuery. Namely, the description of what values are acceptable etc. I guess we have to postpone that for now and re-use what we will decide when we discuss hydra:Operation and hydra:expects.



>>> templated link is pretty straigh forward with a well defined range, which is 
>>> an IriTemplate, which exactly fits your example. Indeed, hydra:freetextQuery 
>>> is fuzzy as it takes in theory an user's input, but doesn't bind that input 
>>> with any particular property thus it might be not suitable in many 
>>> situations.
>>
>> That's a different kind of fuzzy (string matching).
>
> Indeed.
>
>>> </collection> hydra:search [
>>>      hydra:template "/collection?first={?first}&last={?last}",
>>>      hydra:mapping [ hydra:variable "first"; hydra:property 
>>> schema:givenName ],
>>>      hydra:mapping [ hydra:variable "last"; hydra:property 
>>> schema:familyName ]] .
>>> 
>>> The only case I acknowledge to have something special would be a situation 
>>> when the property's desired value is from user input, but that would bind 
>>> whole template and it's mapping to that logic, which I believe would do more 
>>> harm than good. I'd go with either mapping modification or special 
>>> predicates in the variable mapping.
>>> 
>>> Please note that we're talking about two properties here:
>>> 1. Property of which value we want to filter on - from your example I assume 
>>> that this is a case
>>
>> Yes
>
> Clear
>>
>>> 2. Property from which we want to take a value into the IriTemplate - I 
>>> think this logic is reflected in the hydra:IriTemplateMapping as in the 
>>> freetextQuery example; property defines an input for the template variables, 
>>> not on which property to filter on (or how I understand the spec).
>>> 
>>> Please feel free to deliberate on this as I'm deeply involved in similar 
>>> concerns with my experiences with Hydra.
>>>> 
>>>> Additional clarifications:
>>>> – if a parameter value is empty, it is ignored (i.e., an empty value does
>>>> not mean the property needs to be empty)

How will we be able to express that then?


>>>> – if a filter contains multiple conditions, each of the result items
>>>> must match *all* of the conditions
>>>> Examples:
>>>> – /collection?first=Markus&last= returns a collection of items with
>>>> first name "Markus"
>>>> – /collection?first=Markus&last=Lanthaler returns a collection of items
>>>> with first name "Markus" and last name "Lanthaler". Items that only
>>>> meet one of these conditions are not returned.

Are we sure that is all we need? How would we extend the model if we find out later that we need more operators?


Cheers,
Markus


>>>> [1] https://github.com/HydraCG/Specifications/issues/45


--
Markus Lanthaler
@markuslanthaler

Received on Thursday, 29 October 2015 21:52:38 UTC