From b3df5b8d56cdddbfaf9303d45e7ab9c0f1fc55fd Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 4 Apr 2016 14:25:23 +0100 Subject: [PATCH] findAnnotations: match some fields case-sensitively MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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.) --- pandora/annotation/managers.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/pandora/annotation/managers.py b/pandora/annotation/managers.py index de050e10a..f76127dad 100644 --- a/pandora/annotation/managers.py +++ b/pandora/annotation/managers.py @@ -7,6 +7,12 @@ from oxdjango.query import QuerySet from item.utils import decode_id +case_sensitive_keys = ( + 'public_id', + 'layer', + 'item__public_id', +) + def parseCondition(condition, user): ''' @@ -53,14 +59,24 @@ def parseCondition(condition, user): v = decode_id(v) if isinstance(v, bool): #featured and public flag key = k - elif k in ('lat', 'lng', 'area', 'south', 'west', 'north', 'east', 'matches', - 'id', 'places__id', 'events__id'): + elif k in ('places__id', 'events__id'): key = "%s%s" % (k, { '>': '__gt', '>=': '__gte', '<': '__lt', '<=': '__lte', }.get(op, '')) + elif k in case_sensitive_keys: + key = "%s%s" % (k, { + '>': '__gt', + '>=': '__gte', + '<': '__lt', + '<=': '__lte', + '==': '__exact', + '=': '__contains', + '^': '__startswith', + '$': '__endswith', + }.get(op, '__contains')) else: key = "%s%s" % (k, { '>': '__gt', @@ -75,7 +91,9 @@ def parseCondition(condition, user): key = str(key) 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: q = ~Q(**{key: v}) else: @@ -152,7 +170,7 @@ class AnnotationManager(Manager): #join query with operator qs = self.get_query_set() - + conditions = parseConditions(data.get('query', {}).get('conditions', []), data.get('query', {}).get('operator', '&'), user)