Re: [Feature Request] Shorthand syntax for filtering aggregations

2017-04-12 Thread Ian Foote
Hi Tom,

I really like the look of Count('emails').filter(unread=False) in the
annotate call.

Ian

On 12/04/17 21:35, Tom Forbes wrote:
> Hello,
> At the Djangocon sprints I wanted to add support for a postgres specific
> syntax for filtering aggregations, which is quite simple: MAX(something)
> FILTER (WHERE x=1).
> 
> During this the sprints I was told that it would be good to support this
> for all databases, and it can be done using the CASE syntax: MAX(CASE
> WHEN x=1 THEN something END).
> 
> Doing this with the ORM is quite verbose, it would be really nice to be
> able to have a shorthand syntax for filtering aggregates that can use
> database-specific syntax where available (the postgres syntax is faster
> than the CASE syntax). I've made a proof of concept merge request that
> implements this here:
> 
> https://github.com/django/django/pull/8352
> 
> I'd really like some feedback and to maybe have a discussion about what
> the API could look like. Currently I went for adding `.filter()` and
> `.exclude()` methods to the base Aggregate class. I like this approach
> as it's close to the familiar queryset syntax but I understand there are
> subtleties with combining them (I just AND them together currently).
> It's also better to be consistent - if we can't support all of the
> queryset filter() syntax then we shouldn't confuse people by having a
> filter method that acts differently.
> 
> An example of the API is this:
> 
> Mailboxes.objects.annotate(
>read_emails=Count('emails').filter(unread=False),
>unread_emails=Count('emails').filter(unread=True),
>recent_emails=Count('emails').filter(received_date__lt=one_week_ago)
> )
> 
> 
> I'd really like some feedback on what the API should look like. Is
> filter a good idea? Any feedback on the current merge request
> implementation is appreciated as well, I'm fairly new to the Django
> expression internals. I think I'm going the right way with having a
> separate FilteredAggregate expression but I'm not sure.
> 
> Many thanks,
> Tom
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-developers+unsubscr...@googlegroups.com
> .
> To post to this group, send email to django-developers@googlegroups.com
> .
> Visit this group at https://groups.google.com/group/django-developers.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/CAFNZOJM0HDNCeLta6L9u7uJY7usJWn5u8ZYO4S8cDFOeOLYgGQ%40mail.gmail.com
> .
> For more options, visit https://groups.google.com/d/optout.


-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/736674a7-334c-2527-b84e-0e2f949f8685%40feete.org.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: OpenPGP digital signature


[Feature Request] Shorthand syntax for filtering aggregations

2017-04-12 Thread Tom Forbes
Hello,
At the Djangocon sprints I wanted to add support for a postgres specific
syntax for filtering aggregations, which is quite simple: MAX(something)
FILTER (WHERE x=1).

During this the sprints I was told that it would be good to support this
for all databases, and it can be done using the CASE syntax: MAX(CASE WHEN
x=1 THEN something END).

Doing this with the ORM is quite verbose, it would be really nice to be
able to have a shorthand syntax for filtering aggregates that can use
database-specific syntax where available (the postgres syntax is faster
than the CASE syntax). I've made a proof of concept merge request that
implements this here:

https://github.com/django/django/pull/8352

I'd really like some feedback and to maybe have a discussion about what the
API could look like. Currently I went for adding `.filter()` and
`.exclude()` methods to the base Aggregate class. I like this approach as
it's close to the familiar queryset syntax but I understand there are
subtleties with combining them (I just AND them together currently). It's
also better to be consistent - if we can't support all of the queryset
filter() syntax then we shouldn't confuse people by having a filter method
that acts differently.

An example of the API is this:

Mailboxes.objects.annotate(
   read_emails=Count('emails').filter(unread=False),
   unread_emails=Count('emails').filter(unread=True),
   recent_emails=Count('emails').filter(received_date__lt=one_week_ago)
)


I'd really like some feedback on what the API should look like. Is filter a
good idea? Any feedback on the current merge request implementation is
appreciated as well, I'm fairly new to the Django expression internals. I
think I'm going the right way with having a separate FilteredAggregate
expression but I'm not sure.

Many thanks,
Tom

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAFNZOJM0HDNCeLta6L9u7uJY7usJWn5u8ZYO4S8cDFOeOLYgGQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.