Changing the default operator from OR to AND in So

2020-05-20 09:06发布

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.

The first thing I tried was to to change defaultOperator in schema.xml which did not have the desired effect (it started using AND between fields, not keywords).

<solrQueryParser defaultOperator="AND"/>

I then read about LocalParams and tried adding that to several requestHandler sections in solrconfig.xml (I'm just guessing where it's supposed to go, I can't find any helpful documentation).

<requestHandler name="magento_en" class="solr.SearchHandler">
    <lst name="defaults">
        <str name="q.op">AND</str>

I also poked around in the code (app/core/core/Enterprise/Search), hard-coded {!q.op=AND} to the queries but still couldn't get it to work.

I imagine it's a simple configuration change, can anyone point me in the right direction?

Edit: To clarify, a search for "red jacket" (without quotes) should return results for "red AND jacket". I'm only interested in products that are actually red jackets, not red shoes and/or blue jackets. A manual search for "red AND jacket" returns the results that I'm after.

Currently a search performs these queries:

INFO: [] webapp=/solr path=/select params={start=0&q=articles_title:red+jacket*+articles_summary:red+jacket*+articles_text:red+jacket*+cms_title:red+jacket*+cms_content:red+jacket*&json.nl=map&wt=json&fq=store_id:1+store_id:0&version=1.2&rows=4} hits=7 status=0 QTime=1 
09/01/2013 10:46:21 AM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/select params={spellcheck=true&sort=attr_sort_score_en+desc&spellcheck.extendedResults=true&json.nl=map&wt=json&spellcheck.collate=true&version=1.2&rows=1&fl=id&start=0&q=(Red+jacket)&spellcheck.dictionary=magento_spell_en&q.op=AND&spellcheck.count=2&qt=magento_en&fq=(visibility:3+OR+visibility:4)+AND+store_id:1} hits=645 status=0 QTime=5 
09/01/2013 10:46:21 AM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/select params={facet=on&sort=score+desc&json.nl=map&wt=json&version=1.2&rows=24&fl=id&start=0&facet.query=category_ids:8&facet.query=category_ids:46&facet.query=category_ids:88&facet.query=category_ids:126&facet.query=category_ids:168&facet.query=category_ids:180&facet.query=category_ids:207&facet.query=category_ids:224&facet.query=category_ids:242&facet.query=category_ids:276&q=(Red+jacket)&q.op=AND&facet.field=attr_nav_multi_colourway&qt=magento_en&fq=(visibility:3+OR+visibility:4)+AND+store_id:1} hits=645 status=0 QTime=5 
09/01/2013 10:46:22 AM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/select params={facet=on&sort=attr_sort_score_en+desc&json.nl=map&wt=json&rows=100&version=1.2&start=0&facet.query=category_ids:8&facet.query=category_ids:46&facet.query=category_ids:88&facet.query=category_ids:126&facet.query=category_ids:168&facet.query=category_ids:180&facet.query=category_ids:207&facet.query=category_ids:224&facet.query=category_ids:242&facet.query=category_ids:276&q=(Red+jacket)&q.op=AND&facet.field=attr_nav_multi_colourway&qt=magento_en&fq=(visibility:3+OR+visibility:4)+AND+store_id:1} hits=645 status=0 QTime=6 
09/01/2013 10:46:22 AM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/select params={facet=on&sort=attr_sort_score_en+desc&json.nl=map&wt=json&rows=100&version=1.2&start=0&facet.query=category_ids:8&facet.query=category_ids:46&facet.query=category_ids:88&facet.query=category_ids:126&facet.query=category_ids:168&facet.query=category_ids:180&facet.query=category_ids:207&facet.query=category_ids:224&facet.query=category_ids:242&facet.query=category_ids:276&q=(Red+jacket)&q.op=AND&facet.field=attr_nav_multi_colourway&qt=magento_en&fq=(visibility:3+OR+visibility:4)+AND+store_id:1} hits=645 status=0 QTime=3 

标签: magento solr
6条回答
Lonely孤独者°
2楼-- · 2020-05-20 09:14

I ended up using q.op which changed the operator to AND instead of OR. For example:

 ?q=text:small cars&q.op=AND
查看更多
等我变得足够好
3楼-- · 2020-05-20 09:18

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.

查看更多
够拽才男人
4楼-- · 2020-05-20 09:28

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

查看更多
冷血范
5楼-- · 2020-05-20 09:31
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
查看更多
Emotional °昔
6楼-- · 2020-05-20 09:32

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.

查看更多
祖国的老花朵
7楼-- · 2020-05-20 09:32

To answer my own question, I ended up overriding the Enterprise_Search_Model_Adapter_HttpStream model to inject ANDs 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.

查看更多
登录 后发表回答