findAnnotations: match some fields case-sensitively

Requiring layer to have the right case is consistent with
addAnnotation(), and means the _layer[_like] index can be used. In my
testing, if itemsQuery specifies a single item, then postgres doesn't
bother with the layer index anyway; but if not, it makes a pretty big
(~3×) difference.

Matching public_id and item__public_id case-sensitively also seems
reasonable (it's consistent with get() and getAnnotation()).

(Is lower() redundant for the case-insensitive comparisons? ie. is
UPPER(x.lower()) == UPPER(x)? I'm not sure, it's cheap, let's leave it.)
This commit is contained in:
Will Thompson 2016-04-04 14:25:23 +01:00
parent 8d1b4de337
commit b3df5b8d56

View file

@ -7,6 +7,12 @@ from oxdjango.query import QuerySet
from item.utils import decode_id from item.utils import decode_id
case_sensitive_keys = (
'public_id',
'layer',
'item__public_id',
)
def parseCondition(condition, user): def parseCondition(condition, user):
''' '''
@ -53,14 +59,24 @@ def parseCondition(condition, user):
v = decode_id(v) v = decode_id(v)
if isinstance(v, bool): #featured and public flag if isinstance(v, bool): #featured and public flag
key = k key = k
elif k in ('lat', 'lng', 'area', 'south', 'west', 'north', 'east', 'matches', elif k in ('places__id', 'events__id'):
'id', 'places__id', 'events__id'):
key = "%s%s" % (k, { key = "%s%s" % (k, {
'>': '__gt', '>': '__gt',
'>=': '__gte', '>=': '__gte',
'<': '__lt', '<': '__lt',
'<=': '__lte', '<=': '__lte',
}.get(op, '')) }.get(op, ''))
elif k in case_sensitive_keys:
key = "%s%s" % (k, {
'>': '__gt',
'>=': '__gte',
'<': '__lt',
'<=': '__lte',
'==': '__exact',
'=': '__contains',
'^': '__startswith',
'$': '__endswith',
}.get(op, '__contains'))
else: else:
key = "%s%s" % (k, { key = "%s%s" % (k, {
'>': '__gt', '>': '__gt',
@ -75,7 +91,9 @@ def parseCondition(condition, user):
key = str(key) key = str(key)
if isinstance(v, unicode): if isinstance(v, unicode):
v = unicodedata.normalize('NFKD', v).lower() v = unicodedata.normalize('NFKD', v)
if v not in case_sensitive_keys:
v = v.lower()
if exclude: if exclude:
q = ~Q(**{key: v}) q = ~Q(**{key: v})
else: else: