2011-11-18 29 views
14

Estoy usando python's mongoengine para consultar MongoDB, y me ha encantado en su mayor parte, pero estoy teniendo un problema con un advanced query.MongoDB usando una cláusula OR en mongoengine

Aquí es mi modelo

class ContentItem(Document): 
    account = ReferenceField(Account) 
    creator = ReferenceField(User) 
    public = BooleanField(default=False) 
    last_used = DateTimeField(default=datetime.now) 

me gustaría hacer una consulta para todos ContentItem 's que son de una cuenta en particular, y son o creado por el usuario conectado o son públicos. Aquí está la consulta escribí

query = ContentItem.objects.filter((Q(account=account) & Q(public=True)) | (Q(account=account) & Q(creator=logged_in_user))).order_by('-last_used') 

o:

query = ContentItem.objects.filter(Q(account=account) & (Q(public=True) | Q(creator=logged_in_user))).order_by('-last_used') 

Pero estos parecen ser XOR en la que si bien public, o la creator pero no ambos. Es esto esperado?

¿Estoy pasando por alto algo? ¿Debo hacer esto directamente con mongodb en lugar de mongoengine?

Mi solución actual consiste en realizar dos consultas diferentes y combinar los resultados, pero a medida que el n. ° de elementos de contenido aumenta, el resultado tarda mucho en volver porque necesito obtener todos los elementos antes de poder ordenarlos, perdiendo así todo el beneficio de los resultados paginados (django).

Respuesta

6

La documentación de mongoengine es aparentemente incorrecta en este caso. En lugar de utilizar los operadores bit a bit "&" y "|", debe usar los operadores estándar "y" y "o".

Así que su primera consulta se convierte en:

query = ContentItem.objects.filter((Q(account=account) and Q(public=True)) or (Q(account=account) and Q(creator=logged_in_user))).order_by('-last_used') 
+0

que hizo el truco. Agregué una nota en la cuenta de github para arreglar la documentación https://github.com/hmarr/mongoengine/issues/363 – MattoTodd

+0

Este NO es el caso; vea el problema github mencionado anteriormente. Intenté esto, pero usar 'o' en vez de' | 'no aplicará el filtro. Usar '&' y '|' funciona bien para mí. – Paul

+2

@Paul - ¿Tal vez no se dio cuenta de que esta publicación tenía 9 meses y que el error ya se solucionó? – apiguy

2

La forma correcta de hacer la consulta es de utilice operaciones bit a bit | y & la forma en que lo escribió en su pregunta:

query = ContentItem.objects.filter((Q(account=account) & Q(public=True)) | (Q(account=account) & Q(creator=logged_in_user))).order_by('-last_used') 

Nota: el uso de los operadores booleanos estándar Python and y or se no trabajo. Esto se explica en el MongoEngine documentation.

0

ustedes probablemente importar el mal Q

from mongoengine.queryset.visitor import Q as mongo_Q

from django.db.models import Q as normal_Q

Cuestiones relacionadas