Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB using an OR clause in mongoengine

Tags:

I'm using python's mongoengine to query MongoDB, and have loved it for the most part, but I'm having an issue with an advanced query.

Here's my model

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

I would like to make a query for all ContentItem's that are of a particular account, and are either created by the logged in user or are public. Here's the query I wrote

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

or:

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

But these seem to be XOR where if either public, or the creator but not both. Is this expected?

Am I overlooking something? Should I do this directly with mongodb instead of mongoengine?

My current workaround is to make two different queries and combine the results, but as the # of Content Items gets larger the result is taking a long time to come back because I need to get all items before I can order them, thereby losing all the benefit of (django) paginated results.

like image 921
MattoTodd Avatar asked Nov 18 '11 22:11

MattoTodd


People also ask

How do you query in MongoEngine?

The connect() function returns a MongoClient object. Using list_database_names() method available to this object, we can retrieve number of databases on the server. It is also possible to obtain list of collections in a database, using list_collection_names() method.

Should I use PyMongo or MongoEngine?

Both PyMongo and MongoEngine can be used to access data from a MongoDB database. However, they work in very different ways and offer different features. PyMongo is the MongoDB recommended library. It makes it easy to use MongoDB documents and maps directly to the familiar MongoDB Query Language.


2 Answers

MongoEngine docs say otherwise. Please check this: http://docs.mongoengine.org/guide/querying.html

like image 113
Richil Avatar answered Sep 18 '22 13:09

Richil


The mongoengine documentation is apparently incorrect in this case. Instead of using the bitwise operators "&" and "|", you should use the standard operators "and" and "or".

So your first query becomes:

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')
like image 41
apiguy Avatar answered Sep 21 '22 13:09

apiguy