using OR and NOT in solr query
Asked Answered
D

7

86

I'm working on a solr query similar to the following:

((myField:superneat AND myOtherField:somethingElse) OR NOT myField:superneat)

When running this, no results are returned. Using criteria on either side of the OR NOT returns results that I'd expect - they are just not working well together. In the case that myField matches superneat, I'm intending to also ensure that myOtherField is set to somethingElse, but if myField is not superneat, include it in the results.

Can someone explain why solr is not returning results for this kind of query? Should the query be restructured somehow - or is there a different way in which solr can be used to achieve the desired result?

Disturb answered 11/3, 2009 at 14:34 Comment(0)
A
84

I don't know why that doesn't work, but this one is logically equivalent and it does work:

-(myField:superneat AND -myOtherField:somethingElse)

Maybe it has something to do with defining the same field twice in the query...

Try asking in the solr-user group, then post back here the final answer!

Artichoke answered 11/3, 2009 at 15:41 Comment(7)
Thank you for your help! This does indeed work - and I have posed this to the solr-user group. I'll post any useful things I hear from them here.Disturb
Note that -myField:superneat OR myOtherField:somethingElse would also be the same and is slightly simpler.Kokand
@YorickSijsling the point is that even though logically equivalent, Solr sometimes doesn't cope very well with purely negative queries like the one the OP posted or the one you posted.Artichoke
@Mauricio Scheffer - I would question that entirely. Could you explain more on how it doesn't cope very well? We run rather complex conditionals here and found it copes very well with billions of documents.Kiblah
@Kiblah "complex conditionals" != "purely negative queries". Also, things might have improved in recent versions of Solr, I haven't checked.Artichoke
In Solr 4.1 I get this problem on date ranges, like you answered here: #1344294Schooner
I found that as of Solr 3.6, if I wanted to do a negative query OR'd with another condition I needed to do "( -myfield:myValue ) OR myField:otherValue". If I did not include spaces within the parenthesis, it did not parse. I think that is corrected in 4+.Rock
M
44
Instead of "NOT [condition]" use "(*:* NOT [condition])"
Mascia answered 21/8, 2009 at 20:20 Comment(1)
Thanx alot! This one worked for me even for complex queries while -(myField:superneat AND -myOtherField:somethingElse) approach - didn't!Aetiology
A
37

Solr currently checks for a "pure negative" query and inserts *:* (which matches all documents) so that it works correctly.

-foo is transformed by solr into (*:* -foo)

The big caveat is that Solr only checks to see if the top level query is a pure negative query! So this means that a query like bar OR (-foo) is not changed since the pure negative query is in a sub-clause of the top level query. You need to transform this query yourself into bar OR (*:* -foo)

You may check the solr query explanation to verify the query transformation:

?q=-title:foo&debug=query

is transformed to

(+(-title:foo +MatchAllDocsQuery(*:*))
Almazan answered 28/1, 2014 at 15:1 Comment(1)
edismax handles nested pure negative queries correctly, right? Has there been any discussion about patching the Lucene query parser to support these in the same way?Erring
F
26

Putting together comments from a couple different answers here, in the Solr docs and on the other SO question, I found that the following syntax produces the correct result for my use case

(my_field=my_value or my_field is null):

(my_field:"my_value" OR (*:* NOT my_field:*))

This works for solr 4.1.0. This is slightly different than the use case in the OP; but, I thought that others would find it useful.

Forster answered 24/3, 2014 at 17:34 Comment(1)
Ran into exactly this scenario today in Solr 5, and this suggestion works.Polygyny
D
10

You can find the follow up to the solr-user group on: solr user mailling list

The prevailing thought is that the NOT operator may only be used to remove results from a query - not just exclude things out of the entire dataset. I happen to like the syntax you suggested mausch - thanks!

Disturb answered 13/3, 2009 at 12:27 Comment(0)
P
5

Just to add another unexpected case, here is query that wasn't returning expected results:

*:* AND ( ( field_a:foo AND field_b:bar ) OR !field_b:bar )

field_b in my case is something I perform faceting on, and needed to target the query term "foo" only on that type (bar)

I had to insert another *:* after the or condition to get this to work, like so:

*:* AND ( ( field_a:foo AND field_b:bar ) OR ( *:* AND !field_b:bar ) )

edit: this is in solr 6.6.3

Pragmatic answered 17/10, 2018 at 14:26 Comment(0)
M
-2

simple do id:("12345") OR id:("7890") .... and so on

Makowski answered 1/5, 2020 at 6:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.