在 Solr 查询中使用 OR 和 NOT

我正在处理一个类似于以下的 solr 查询:

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

运行此命令时,不返回任何结果。在 OR NOT 的任何一边使用条件都会返回我所期望的结果——它们只是不能很好地协同工作。在 我的领域超级棒匹配的情况下,我还打算确保 我的其他领域被设置为 别的东西,但是如果 我的领域不是 超级棒,则在结果中包含它。

有人能解释一下为什么 solr 没有返回这种查询的结果吗?是否应该以某种方式重新构造查询-或者是否有不同的方式可以使用 solr 来实现期望的结果?

119788 次浏览

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!

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!

Instead of "NOT [condition]" use "(*:* NOT [condition])"

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(*:*))

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.

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

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