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:
parent
8d1b4de337
commit
b3df5b8d56
1 changed files with 22 additions and 4 deletions
|
@ -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:
|
||||||
|
@ -152,7 +170,7 @@ class AnnotationManager(Manager):
|
||||||
|
|
||||||
#join query with operator
|
#join query with operator
|
||||||
qs = self.get_query_set()
|
qs = self.get_query_set()
|
||||||
|
|
||||||
conditions = parseConditions(data.get('query', {}).get('conditions', []),
|
conditions = parseConditions(data.get('query', {}).get('conditions', []),
|
||||||
data.get('query', {}).get('operator', '&'),
|
data.get('query', {}).get('operator', '&'),
|
||||||
user)
|
user)
|
||||||
|
|
Loading…
Reference in a new issue