2013-02-21 1 views
7

У меня есть следующие модели:mongoengine - запрос, как фильтровать по размеру ListField

class Like(EmbeddedDocument): 
    user = ReferenceField(User,dbref=False) 
    date = DateTimeField(default=datetime.utcnow,required=True) 
    meta = {'allow_inheritance': False} 

class Post(Document): 
    name = StringField(max_length=120, required=True) 
    likes = ListField(EmbeddedDocumentField(Like)) 

Я хотел бы, чтобы отфильтровать только сообщения с более чем 20 Понравилось (ListField размером более 20). Я попытался выполнить запрос:

posts = Post.objects.filter(likes__size_gte=20) 
posts = Post.objects.filter(likes_gte=20) 
posts = Post.objects.filter(likes__gte=20) 
posts = Post.objects.filter(likes__size_gte=20) 

Ни один из них не работает.

Но если я использую точное совпадение (размер ListField ровно 20 любит) он работает:

posts = Post.objects.filter(likes__size=20) 

Комментарии?

ответ

8

далеко не идеальное решение, но вы можете сделать с сырым запроса Монго и оператора $where, например:

posts = Post.objects.filter(__raw__={'$where': 'this.likes.length > 20'}) 

Другой вариант, который должен работать быстрее, но менее ясно, на мой взгляд , чтобы проверить, существует ли элемент 21th:

posts = Post.objects.filter(likes__21__exists=True) 

Второй вариант работает только если вы используете MongoDB 2.2 +

Источник: T из этих answers и применяется к MongoEngine.

+0

Это хороший хак. Tks. Мне любопытно, если использование «длины» не будет дорогостоящим на сервере. – rat

+1

Да, это немного дорого. Вы в основном оцениваете функцию (в данном случае 'длина> 20') для каждого документа. Версия 'exist' должна быть намного более эффективной ... – yprez

+0

Из документов mongo: http://docs.mongodb.org/manual/reference/operator/query/where/ – yprez

4

Вы не можете использовать $ size для диапазона значений.

С сайта Монго в:

$ размер не принимает диапазоны значений. Чтобы выбрать документы на основе полей с разными номерами элементов , создайте поле счетчика, которое вы увеличиваете при добавлении элементов в поле.

Это ссылка на соответствующий вопрос, который привел к ответу: remove documents with array field's size less than 3 in mongoDB

Это страница Монго, что предыдущая ссылка связана, давшая документацию в блоке вверх выше: http://docs.mongodb.org/manual/reference/operator/size/#_S_size

Попробуйте добавить поле счетчика, как предлагается в текстовом блоке.

+0

Спасибо. Знаете ли вы, есть ли какой-либо план для реализации этой функции? – rat

+0

В последующих выпусках ничего не говорится о том, что это изменится, но я не знаю никаких знаний о разработке, выходящих за рамки выпуска 2.2.4. Я полагаю, что причина заключается в том, чтобы что-то делать конкретно с тем, как размер $ реализуется под капюшоном, что они так на самом деле не знают, но я никогда не смотрел, поэтому я точно не знаю. – egreene