UniqueValidator is resulting in regex query rather than an equality check
bazinga012 opened this issue · 2 comments
UniqueValidator is resulting in regex queries which is impacting performace.
Consider the following situation:
from mongoengine import Document
class MyModel(Document):
my_field = StringField(required=True, unique=True)
from rest_framework_mongoengine import serializers
class MyModelSerializer(serializers.DocumentSerializer):
class Meta:
model = MyModel
fields = '__all__'
MyModelSerializer(data=payload).is_valid()
This call to is_valid() will result in query for checking uniqueness of my_field by the UniqueValidator with lookup value being "exact".
class UniqueValidator(object):
"""
Validator that corresponds to `unique=True` on a model field.
Should be applied to an individual field on the serializer.
"""
message = _('This field must be unique.')
def __init__(self, queryset, message=None, lookup='exact'):
self.queryset = queryset
self.serializer_field = None
self.message = message or self.message
self.lookup = lookup
for "exact" lookup mongoengine generates a regex query(as shown below)
mongoengine/fields.py
def prepare_query_value(self, op, value):
if not isinstance(op, six.string_types):
return value
if op.lstrip('i') in ('startswith', 'endswith', 'contains'):
flags = 0
if op.startswith('i'):
flags = re.IGNORECASE
op = op.lstrip('i')
regex = r'%s'
if op == 'startswith':
regex = r'^%s'
elif op == 'endswith':
regex = r'%s$'
elif op == 'exact':
regex = r'^%s$'
so query will be of the form: find({"field_name": /^<value_from_payload>$/})
This regex is resulting in performance hit.
If I override the constructor in rest_framework_mongoengine
class UniqueValidator(MongoValidatorMixin, validators.UniqueValidator):
def __init__(self, queryset, message=None, lookup=''):
return super(UniqueValidator, self).__init__(queryset, message, lookup)
This results in find query with equality check(rather than regex).
Can we have this change or is there any other way to achieve the equality query rather than a regex query?
Hi! I'm sorry, I don't have time even for updating for breaking changes, not speaking about performance.
If you decide to modify this on your own, pull requests are welcome.