#27719: Add queryset.alias() to mimic .annotate() for aggregations without 
loading
data
-------------------------------------+-------------------------------------
     Reporter:  Marc Tamlyn          |                    Owner:  nobody
         Type:  New feature          |                   Status:  new
    Component:  Database layer       |                  Version:  master
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Marc Tamlyn):

 I take your point about the select list, most of those APIs (e.g. values,
 distinct) do indeed require the field to be selected making alias slightly
 redundant.

 For me it's very explicitly not a hack, and the fact we can use annotate
 is the hack. But that's bikeshedding.

 More practically, consider this code:

 {{{
 query = SearchQuery('some term')
 return qs.alias(
    main_vector=SearchVector('title', 'body'),
    secondary_vector=SearchVector('parent__title', 'parent__body'),
 ).alias(
    vector=F('main_vector') + F('secondard_vector'),
 ).alias(
    rank=Case(
       When(vector__search=query, then=SearchRank('vector', query)),
       When(secondary_vector__search=query,
 then=SearchRank('secondary_vector', query)),
       # other cases here
    )
 ).order_by('-rank')
 }}}

 (I'm aware this example is contrived, but I have some pretty complex
 annotations for reporting, and they're even more fun with `SubQuery`... In
 most of these cases it doesn't matter that this field is in the
 select_list, although it doesn't need to be.

 Here I've actually used the "alias approach" and the "variable approach" -
 one for vectors and one for queries.

 The alias approach has allowed me to:
 - Incrementally build up expressions in the query
 - Name values and potentially reuse them at a later time in the query
 creation phase - perhaps I have some other function which takes the
 returned queryset from this method and counts the records where the rank
 is > 0.7 to give an indication of strong matching results, then without
 the naming from annotate or alias I'd have to access or recreate the
 component expressions. Rank is an int, so again it doesn't really matter
 to have it queryable.

 I think  #25367 is an important piece of work, and it would help solve the
 performance problem by allowing unselected values. I think though that
 there is a merit in being able to create a "virtual field" using an
 expression, and use it in subsequent querysets. This would be an easier
 solution to this particular performance issue, and it also gives the user
 explicit API control over the select list where needed, rather than
 implicitly by how you used your expression. It's not an either/or
 scenario.

--
Ticket URL: <https://code.djangoproject.com/ticket/27719#comment:6>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/066.614ebf34b122a6bfe99d072b4d56929f%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to