More Any and All

The Data Services team has starting thinking about adding Any/All support to Data Services and we noticed a couple of things that I think warrant minor changes to the proposal. So as always I wanted to share and get your thoughts.

New separator

The original any/all proposal suggested using a ',' to separate the range variable from the predicate, e.g:

~/Movies/?$filter=any(Actors a, a/Name eq 'John Belushi')

I think this has a problem. Usually ',' is used to separate similar things, like the parameters to a function, but in this case it separates a Lambda Parameter from a Predicate. Clearly these things are not the same, moreover using ',' would confuse things in the future if we ever allowed calling custom functions with multiple parameters in the filter.

I think this means we need something more lambda-ish, perhaps something like this:

~/Movies/?$filter=any(Actors a: a/Name eq 'John Belushi')

This uses ':' instead of ','. There is even a precedent for using ':' in lambdas, python uses ':' like this:

lambda a: a+1

More importantly this makes sense in OData because:

  • ':' is explicitly allowed in querystrings, in fact it is in a list of suggested scheme specific separators called out in RFC 3986.
  • Using a single character (as opposed to something like => or ->) makes more sense in a URL that needs to be concise.

Shorthand Syntax

While thinking through scenarios for any/all, I noticed that I was often writing queries like this:

~/Movies/?$filter=any(Awards a: true)

Or this:

~/Movies/?$filter=any(Actors a: any(a/Awards aw: true))

In both cases the predicate really doesn't matter, so requiring 'true' seems a little bit like a quiz.

The proposal then is to add a shorter (and easier to understand) 'overload':

~/Movies/?$filter=any(Awards)
~/Movies/?$filter=any(Actors a: any(a/Awards))

I think you'll agree this is a lot easier to understand.

Conclusion

Hopefully these proposals are not too controversial, either way though I'm very keen to hear your thoughts. Do you think they make sense?

Alex

  1. Posted Wednesday, February 09, 2011 at 12:40:00 PM

    @James - yes that's right.<br/> <br/> @James & Chris - well we just copied the LINQ Any/All operators - really just going for consistency. <br/> <br/> In fact this:<br/> <br/> from m in ctx.Movies<br/> where m.Awards.Any()<br/> select m;<br/> <br/> Will translate to:<br/> <br/> ~/Movies/?$filter=any(Awards)<br/> <br/>

  2. Posted Tuesday, February 08, 2011 at 10:28:03 AM

    I like the the ":" syntax better myself.<br/> <br/> I have to agree with James if 'having' is a better identifier than 'any'.<br/> <br/> I see the what 'any' portrays but I still like 'having' a little better.

  3. Posted Tuesday, February 08, 2011 at 6:57:46 AM

    I reckon the use of ":" is definitely cleaner.<br/> <br/> Just want to make sure I an understanding how this is working.<br/> <br/> This example ~/Movies/?$filter=any(Awards) will return any movies that have awards?<br/> <br/> This example ~/Movies/?$filter=any(Actors a: any(a/Awards)) will return any movies with Actors that have awards?<br/> <br/> If my assumption is correct I wonder if 'having' instead of 'any' would be more readable or does it have to be 'any'?<br/> <br/> Cheers,<br/> James