I\'m using Solr with Magento Enterprise. I\'m trying to change the default search operator from OR
to AND
to make searches more specific by default.
Thanks to Macilias' link on the dismax parser plugin I've found a way to accomplish this with the settings in the solrconfig.xml. In this file there are requestHandler nodes for a bunch of different languages. I modified the english one since our store is in english. By default the xml looked like this:
<requestHandler name="magento_en" class="solr.SearchHandler">
<lst name="defaults">
<str name="qf">fulltext_1_en^1.0 fulltext_2_en^2.0 fulltext_3_en^3.0 fulltext_4_en^4.0 fulltext_5_en^5.0</str>
<str name="pf">fulltext_1_en^1.0 fulltext_2_en^2.0 fulltext_3_en^3.0 fulltext_4_en^4.0 fulltext_5_en^5.0</str>
<int name="ps">1</int>
<str name="mm">1</str>
<str name="defType">dismax</str>
<str name="echoParams">explicit</str>
<str name="spellcheck.onlyMorePopular">false</str>
<str name="spellcheck.extendedResults">false</str>
<str name="spellcheck.count">1</str>
</lst>
<arr name="last-components">
<str>spellcheck</str>
</arr>
</requestHandler>
The important parameter here is "mm" which stands for Minimum 'Should' Match. The dismax parser uses this instead of a default operator to determine how multiple search terms should be handled. A value of 1 means only one term from the query must match (same behavior as OR). A value of 100% mean all the terms must match (same behavior as AND). More complex values can be used as well. Follow the link above for more info. After changing settings in the solrconfig.xml file you'll need to restart the Solr server before they take effect.
This video is also a good Magento Solr resource: http://www.youtube.com/watch?v=07uIJSXdqpU They talk about Minimum Match around the 24 minute mark.
To answer my own question, I ended up overriding the Enterprise_Search_Model_Adapter_HttpStream
model to inject AND
s into the search query. I added the prepareSearchConditions()
method from Enterprise_Search_Model_Adapter_Solr_Abstract
:
<?php
class Foo_Search_Model_Adapter_HttpStream extends Enterprise_Search_Model_Adapter_HttpStream
{
protected function prepareSearchConditions($query)
{
$query = str_replace(' ', ' AND ', str_replace(' AND ', ' ', $query));
return parent::prepareSearchConditions($query);
}
}
It doesn't play nice with other operators obviously but in my case it's good enough™ (at least for now). I'm still hoping to find a better solution though.
Try the following (untested):
q={!q.op=AND df=articles_title}red jacket&fq=articles_summary:(red AND jacket)&fq=articles_text:(red AND jacket)
and the rest of the fields are used in a similar fashion with fq
parameter.
The above will return all those records where all the mentioned fields contain term red and jacket. However, if you are required to return a record where atleast one field contains red AND jacket, then I suggest that you use a copyfield to map all those fields to a single field and then search against the copyfield type.
I ended up using q.op which changed the operator to AND instead of OR. For example:
?q=text:small cars&q.op=AND
My question is not so much about the syntax but where to configure this so it applies to all searches.
To answer your question, I am quite sure that we need to specify the default operator for solrQueryParser in schema.xml and not in solrconfig.xml. As you mentioned, it is given as,
< solrQueryParser defaultOperator="AND"/>
The reason why you did not get expected results may be because of the following reason:
If your search URL is something like,
q=articles_summary:red+jacket
Then what happens is, "red" is searched against field "articles_summary" but "jacket" is searched against your default search field (say "text") which if I am right will be a copy field containing copy of all searchable fields. Hence you will get a match for "red" in "articles_summary" and "jacket" in "text".
To get what you expect, I suggest you use something like following URL after setting default operation to AND as you already did:
q=articles_summary:red+articles_summary:jacket
If you have multiple fields to search, you may have to do like this:
q=articles_summary:red+articles_summary:jacket+articles_title:red+articles_title:jacket
In solr you should use the dismax (or edismax) parser plugin. Here you can set the minimum should match to 100%. you can find more information here