MongoEngine / django-mongoengine

django mongoengine integration
Other
749 stars 208 forks source link

Using list in a "not_contains" query #191

Closed Filipizaum closed 1 year ago

Filipizaum commented 1 year ago

There was something I couldn't do with mongoengine.

I've published it on StackOverflow, but no one could solve the real problem.

So I improved the question and decided to post it here.

I'm trying to filter objects from mongodb using mongoengine==0.22.1 in Django.

Assuming I have the following class:

class Person(Document):
    name = StringField()

I wanna filter all Person objects whose name does not contain the names in a list, e.g.: ["Jhon", "Doe"].

I can achieve this with that code (without a dynamic list):

Person.objects.filter(
    name__not__contains="Jhon"
).filter(
    name__not__contains="Doe"
)

But I wanna do that with only one 'filter' calling passing a dynamic list as the query parameter.

I've already tryed that:

my_list = get_list() # ["Jhon", "Doe"]
Person.objects.filter(name__not__contains=my_list)

But I get the following error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/queryset.py", line 73, in __repr__
    self._populate_cache()
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/queryset.py", line 129, in _populate_cache
    self._result_cache.append(next(self))
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/base.py", line 1565, in __next__
    raw_doc = next(self._cursor)
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/base.py", line 1635, in _cursor
    self._cursor_obj = self._collection.find(self._query, **self._cursor_args)
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/base.py", line 1684, in _query
    self._mongo_query = self._query_obj.to_query(self._document)
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/visitor.py", line 91, in to_query
    query = query.accept(QueryCompilerVisitor(document))
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/visitor.py", line 184, in accept
    return visitor.visit_query(self)
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/visitor.py", line 80, in visit_query
    return transform.query(self.document, **query.query)
  File "/usr/local/lib/python3.9/site-packages/mongoengine/queryset/transform.py", line 120, in query
    value = field.prepare_query_value(op, value)
  File "/usr/local/lib/python3.9/site-packages/mongoengine/fields.py", line 158, in prepare_query_value
    value = re.escape(value)
  File "/usr/local/lib/python3.9/re.py", line 277, in escape
    pattern = str(pattern, 'latin1')
TypeError: decoding to str: need a bytes-like object, list found

Is that possible to achieve what I'm trying to get?

last-partizan commented 1 year ago

contains is a string operation, you need to use name__not__in=my_list.