mongoengine icon indicating copy to clipboard operation
mongoengine copied to clipboard

Advanced queries should use "and" and "or" and not bitwise operators "&" and "|"

Open mattotodd opened this issue 14 years ago • 11 comments

I was using advanced queries and my results were always coming back empty, I found the documentation is incorrect, it says to use "&" and "|" , when you should be using "and" and "or"

mattotodd avatar Nov 21 '11 21:11 mattotodd

mattotodd have you got a test case as we you & and | happily.

rozza avatar Nov 22 '11 08:11 rozza

Some test examples:

https://github.com/hmarr/mongoengine/blob/dev/tests/queryset.py#L2654 https://github.com/hmarr/mongoengine/blob/dev/tests/queryset.py#L2689 https://github.com/hmarr/mongoengine/blob/dev/tests/queryset.py#L2719

rozza avatar Nov 22 '11 08:11 rozza

Ping! any Feedback or shall I close this?

rozza avatar Dec 01 '11 16:12 rozza

Sorry, I have no feedback.

mattotodd avatar Dec 01 '11 16:12 mattotodd

Thanks @mattotodd, unfortunately, I cant reproduce and current testcases use & and | happily - any examples of this not working but and / or working?

rozza avatar Dec 01 '11 16:12 rozza

I'll do my best to explain what I saw (As i ended up using a raw query to get what i was looking for) Also, I am using mongoengine 0.4 if that makes a difference.

I have this document: class ContentItem(Document): account = ReferenceField(Account) creator = ReferenceField(User) public = BooleanField(default=False)

I would like to retrieve all ContentItems that belong to a particular account that are either created by a logged in user or are public

I tried this

items = ContentItem.objects.filter( ( Q(account=account) & Q(creator=logged_in_user) ) | ( Q(account=account) & Q(public=True) ) )

always returns no results (even though it should)

items = ContentItem.objects.filter( Q(account=account) & (Q(creator=logged_in_user) | Q(public=True) ) )

always returns no results (even though it should)

so then i realized the & and | are bitwise selectors, so i tried:

items = ContentItem.objects.filter( ( Q(account=account) and Q(creator=logged_in_user) ) or ( Q(account=account) and Q(public=True) ) )

and this seemed to return results for the first half of the query (account and logged in, but not public)

and so i played around with a whole slew of queries, and none of the results made sense

I ended up using a raw query like so:

items = ContentItem.objects.filter( account=account, raw={'$or': [{'public':True}, {'creator.$id': logged_in_user.id}] } )

and this worked with the results i would expect.

mattotodd avatar Dec 01 '11 17:12 mattotodd

it didn't render raw properly, __ raw __

mattotodd avatar Dec 01 '11 17:12 mattotodd

Hi,

Can you confirm if this works:

items = ContentItem.objects.filter(
    Q(Q(account=account) & Q(creator=logged_in_user)) | 
    Q(Q(account=account) & Q(public=True))
)

rozza avatar Dec 12 '11 09:12 rozza

I have problem with Q it writes that " NameError: global name 'Q' is not defined"

bekatom avatar Feb 02 '13 13:02 bekatom

sorry i forget to import "Q " works fine !!!!

bekatom avatar Feb 02 '13 13:02 bekatom

from mongoengine import Q

result = UserAccount.objects( Q(Q(first_name__istartswith = query[0]) & Q(last_name__istartswith = query[1])) ).only('first_name', 'last_name', 'user_name')

I'm getting a TypeError: init() takes exactly 1 argument (2 given)

praveen001 avatar Nov 05 '13 07:11 praveen001