O365 / python-o365

A simple python library to interact with Microsoft Graph and Office 365 API
Apache License 2.0
1.6k stars 411 forks source link

O365.utils.utils.Query.any does not support negate() and does not follow the group? #1058

Open execcr opened 4 months ago

execcr commented 4 months ago

Hi, i was trying to rewrite this query that is working with Psotman and the O365 messages endpoint: NOT(categories/any(a:a eq 'Category1') or categories/any(a:a eq 'Category2'))

I had thought that this could have been the equivalent code (Note: the operation=ne is not supported with categories):

query = mailbox.new_query()
query.open_group().negate()
query.all(collection='categories', word="Category1", operation='eq')
query.chain('or')
query.any(collection='categories', word=''Category2', operation='eq')
query.close_group()

but the output had the "not" missing: Filter is: {'$filter': "(categories/any(a:a eq 'Category1') or categories/any(a:a eq 'Category2'))"} With the on_Attribute method the filter is producing this output: Query:

query = mailbox.new_query()
query.negate()
query.open_group()
query = query.on_attribute('subject').contains('value1')
query = query.chain('or')
query = query.on_attribute('subject').contains('value2')
query.close_group()

Output: Filter is {'$filter': "(not contains(subject, 'value1') or not contains(subject, 'value2'))"} I would expect this output:

{'$filter': "not(contains(subject, 'value1') or contains(subject, 'value2'))"} any hint?

alejcas commented 4 months ago

query.open_group().negate()

Does nothing.

assign to query again:

query = query.open_group().negate()

and do the same for the following

execcr commented 4 months ago

Thanks, i've tried as you says. The result is the same. The not negation is not added to the filter.

This is the code:

query = mailbox.new_query()
query = query.open_group().negate()
query = query.any(collection='categories', word="Category1", operation='eq')
query = query.chain('or')
query = query.any(collection='categories', word='Category2', operation='eq')
query = query.close_group()

this is the filter created: Filtro creato: {'$filter': "(categories/any(a:a eq 'Category1') or categories/any(a:a eq 'Category2'))"}

alejcas commented 2 months ago

I see! I'll try to fix it

Query can either be a Query object or a string, so pass the string filter you want for now

alejcas commented 2 months ago

Fixed in 094399b2a5d5aab3481e2189d17e563e61c62c81

To negate groups (or anything) the negate should go BEFORE the action, so:

query = mailbox.new_query()
query = query.negate().open_group()  # negate goes first! or otherwise will negate the first any on the group
query = query.any(collection='categories', word="Category1", operation='eq')
query = query.chain('or')
query = query.any(collection='categories', word='Category2', operation='eq')
query = query.close_group()

You can also negate the condition inside the 'any' or 'all' iterables using the negation argument:

query = mailbox.new_query()
query = query.negate().any(collection='categories', word="Category1", operation='eq', negation=True)
print(query)

This outputs:

Filter: not categories/any(a:not a eq 'Category1')
Order: None
Select: None
Expand: None
Search: None

Please report back if this now works as expected

Thanks