diff --git a/docs/guide/querying.rst b/docs/guide/querying.rst index e9e1de24..1cf5ec3c 100644 --- a/docs/guide/querying.rst +++ b/docs/guide/querying.rst @@ -86,6 +86,10 @@ expressions: * ``istartswith`` -- string field starts with value (case insensitive) * ``endswith`` -- string field ends with value * ``iendswith`` -- string field ends with value (case insensitive) +* ``wholeword`` -- string field contains whole word +* ``iwholeword`` -- string field contains whole word (case insensitive) +* ``regex`` -- string field match by regex +* ``iregex`` -- string field match by regex (case insensitive) * ``match`` -- performs an $elemMatch so you can match an entire document within an array diff --git a/mongoengine/fields.py b/mongoengine/fields.py index fd8236a6..11c32f84 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -157,7 +157,7 @@ class StringField(BaseField): regex = r"%s$" elif op == "exact": regex = r"^%s$" - elif op == "has_word": + elif op == "wholeword": regex = r"\b%s\b" elif op == "regex": regex = value @@ -1094,14 +1094,7 @@ class DictField(ComplexBaseField): def prepare_query_value(self, op, value): match_operators = [ - "contains", - "icontains", - "startswith", - "istartswith", - "endswith", - "iendswith", - "exact", - "iexact", + *STRING_OPERATORS ] if op in match_operators and isinstance(value, str): diff --git a/mongoengine/queryset/transform.py b/mongoengine/queryset/transform.py index 375cceb4..cea2ef4c 100644 --- a/mongoengine/queryset/transform.py +++ b/mongoengine/queryset/transform.py @@ -53,8 +53,8 @@ STRING_OPERATORS = ( "iexact", "regex", "iregex", - "has_word", - "ihas_word", + "wholeword", + "iwholeword", ) CUSTOM_OPERATORS = ("match",) MATCH_OPERATORS = ( diff --git a/tests/queryset/test_queryset.py b/tests/queryset/test_queryset.py index cde7dc10..859c4cb5 100644 --- a/tests/queryset/test_queryset.py +++ b/tests/queryset/test_queryset.py @@ -1258,18 +1258,18 @@ class TestQueryset(unittest.TestCase): assert obj is None - # Test has_word - obj = self.Person.objects(name__has_word="Guido").first() + # Test wholeword + obj = self.Person.objects(name__wholeword="Guido").first() assert obj == person - obj = self.Person.objects(name__has_word="rossum").first() + obj = self.Person.objects(name__wholeword="rossum").first() assert obj is None - obj = self.Person.objects(name__has_word="Rossu").first() + obj = self.Person.objects(name__wholeword="Rossu").first() assert obj is None - # Test ihas_word - obj = self.Person.objects(name__ihas_word="rOSSUM").first() + # Test iwholeword + obj = self.Person.objects(name__iwholeword="rOSSUM").first() assert obj == person - obj = self.Person.objects(name__ihas_word="rOSSU").first() + obj = self.Person.objects(name__iwholeword="rOSSU").first() assert obj is None # Test regex @@ -1374,8 +1374,8 @@ class TestQueryset(unittest.TestCase): .filter(name__not__endswith="tum")\ .filter(name__icontains="VAN")\ .filter(name__regex="^Guido")\ - .filter(name__has_word="Guido")\ - .filter(name__has_word="van") + .filter(name__wholeword="Guido")\ + .filter(name__wholeword="van") assert people.count() == 1 def assertSequence(self, qs, expected):