Mongoengine - 使用所有的icontains

时间:2013-04-11 20:40:05

标签: python mongoengine

我见过this question,但它没有回答我的问题,甚至没有回答。

我认为最好用一个例子来解释:

class Blah(Document):
    someList = ListField(StringField())

Blah.drop_collection()

Blah(someList=['lop', 'glob', 'hat']).save()
Blah(someList=['hello', 'kitty']).save()

# One of these should match the first entry
print(Blah.objects(someList__icontains__all=['Lo']).count())
print(Blah.objects(someList__all__icontains=['Lo']).count())

我认为这会打印1, 00, 1(或奇迹般的1, 1),而是会给出

0
Traceback (most recent call last):
  File "metst.py", line 14, in <module>
    print(Blah.objects(someList__all__icontains=['lO']).count())
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 1034, in count
    return self._cursor.count(with_limit_and_skip=True)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 608, in _cursor
    self._cursor_obj = self._collection.find(self._query,
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 390, in _query
    self._mongo_query = self._query_obj.to_query(self._document)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 213, in to_query
    query = query.accept(QueryCompilerVisitor(document))
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 278, in accept
    return visitor.visit_query(self)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 170, in visit_query
    return QuerySet._transform_query(self.document, **query.query)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/queryset.py", line 755, in _transform_query
    value = field.prepare_query_value(op, value)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/fields.py", line 594, in prepare_query_value
    return self.field.prepare_query_value(op, value)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/site-packages/mongoengine/fields.py", line 95, in prepare_query_value
    value = re.escape(value)
  File "/home/blah/.pythonbrew/pythons/Python-3.1.4/lib/python3.1/re.py", line 246, in escape
    return bytes(s)
TypeError: 'str' object cannot be interpreted as an integer

两种查询都无效!

MongoEngine是否支持某种使用icontainsall进行搜索的方式?或者某种方式解决这个问题?

注意:我想使用MongoEngine,而不是PyMongo。

编辑:Python 2.7.3存在同样的问题。

1 个答案:

答案 0 :(得分:1)

截至目前(版本0.8.0),执行此操作的唯一方法是使用__raw__查询,可能与re.compile()结合使用。像这样:

import re

input_list = ['Lo']
converted_list = [re.compile(q, re.I) for q in input_list]

print(Blah.objects(__raw__={"someList": {"$all": converted_list}}).count())

mongoengine目前无法合并allicontains,唯一可以与其他运算符一起使用的运算符是not。这是<{3}}中巧妙地提到的,就像它说:

  

不 - 否定标准支票,可在其他运营商之前使用(例如Q(age_ _mod = 5))

强调我的

但它没有说你不能与其他运营商这样做,实际情况就是如此。


您可以通过查看来源确认此行为:

版本0.8.0+(the docs - 第42-48行):

if parts[-1] in MATCH_OPERATORS:
    op = parts.pop()

negate = False
if parts[-1] == 'not':
    parts.pop()
    negate = True

在旧版本中,可以在_transform_query方法中的 mongoengine / queryset.py 中看到上述行。