Список запросов MongoEngine для объектов, свойства которых начинаются с префиксов, указанных в списке

Мне нужно запросить базу данных Mongo для элементов, которые имеют определенное свойство, начинающееся с любого префикса в списке. Теперь у меня есть такой кусок кода:

query = mymodel(terms__term__in=query_terms)

и это соответствует объектам, у которых есть элемент в списке «terms», у которого StringField «term» явно встречается в списке «query_terms». Чего я хочу добиться, так это наличия объектов, у которых есть элемент в списке «термины», у которого есть «термин» StringField, начинающийся с любого префикса, который встречается в списке «query_terms». Можно ли сделать это в одном запросе и без сохранения всех возможных префиксов «терминов» в базе данных? РЕДАКТИРОВАТЬ: приведенное ниже решение отлично работает, но теперь мне нужно найти объекты с терминами, начинающимися с каждого префикса в списке. я изменил

query = reduce(lambda q1, q2: q1.__or__(q2), 
           map(lambda prefix: Q(terms__term__startswith=prefix)))

to

query = reduce(lambda q1, q2: q1.__and__(q2), 
           map(lambda prefix: Q(terms__term__startswith=prefix)))

но это не работает. В итоге я получаю следующую ошибку:

InvalidQueryError: Duplicate query conditions: terms__term__startswith

Любые идеи?


person k_wisniewski    schedule 27.04.2012    source источник


Ответы (2)


Если вы запрашиваете термин для его значения, вы можете отфильтровать значения, которые начинаются с перфикса, например:

MyModel.objects.filter(terms__term__startswith='foo')

Если вам нужно отфильтровать несколько префиксов, вам нужно будет создать для этого объекты Q:

MyModel.objects.filter(Q(terms__term__startswith='foo') | Q(terms__term__startswith='bar'))

Если вам нужно создать запрос динамически:

prefixes = ['foo', 'bar', 'baz']
query = reduce(lambda q1, q2: q1.__or__(q2), 
               map(lambda prefix: Q(terms__term__startswith=prefix), prefixes))
MyModel.objects.filter(query)
person Filip Dupanović    schedule 27.04.2012

Вы можете использовать регулярное выражение, например ^(prefix1 | prefix2 etc):

prefixes = [....]
regex = '^(%s)' % '|'.join(map(re.escape, prefixes))
docs = your_collection.find({'term': {'$regex': regex}})

upd: не заметил, что этот вопрос касается mongoengine. Вышеупомянутое для чистого pymongo, не знаю, позволяет ли это ME.

person georg    schedule 27.04.2012