cancel
Showing results for 
Search instead for 
Did you mean: 

Solr fulltext search - Solution for multi-field query with "AND"-operator

tino_kissig
Active Participant

We try to figure out how to implement/configure the Solr fulltext search to fit the following requirement: If the the customer puts in the search term e.g. "pants red" the search should only find all the products where each term has been found in any of the fields but not the products where only one of the terms match a field (current implementation).

On Solr query level we do want to have a query like this:

 (
 field1_text_en:pants
 OR 
 field2_en_string_mv:pants
 OR
 field3_text_en_mv:pants
 )
 
 AND 
 
 (
 field1_text_en:red
 OR 
 field2_en_string_mv:red
 OR
 field3_text_en_mv:red
 )


rather then the current solution:

 (
 (field1_text_en:pants OR red)
 OR
 (field2_en_string_mv:pants OR red)
 OR
 (field3_text_en_mv:pants OR red)
 )

As far as we can see de.hybris.platform.solrfacetsearch.search.SearchQuery is not allowing this via its API since it only holds a List of de.hybris.platform.solrfacetsearch.search.QueryFields which will be reused on multiple calls of searchInField and will be then translated to the Solr query above.

Since the current solution depends that much on de.hybris.platform.solrfacetsearch.search.SearchQuery we don't see a solution how to implement/configure this requirement with existing framework.

Cheers,

Tino

aysha_bnl
Explorer
0 Kudos

Is there any concrete solution for this? We have the same requirement and we are unable to find a concrete solution for this? Basically if the search is Women's red pants, solr should bring up all the products which has color as red, gender as women, name as pant.

Accepted Solutions (0)

Answers (5)

Answers (5)

Former Member
0 Kudos

It is not really a solution, but I think it is the only solution for your case. You should override the method 'convertSolrQuery' in the 'DefaultSolrQueryConverter'. There you can change the query of the SolrQuery.

It is something we did also, because we need always to filter on B2BUnit and that was the best solution. (Also with a different AND/OR notation). I have added an example without the B2BUnit logic:

 public class CustomSolrQueryConverter extends DefaultSolrQueryConverter
 {
     private UserService userService;
 
     @Override
     public SolrQuery convertSolrQuery(final SearchQuery searchQuery) throws FacetSearchException
     {
         final SolrQuery res = super.convertSolrQuery(searchQuery);
 
         final UserModel user = userService.getCurrentUser();
         if (user instanceof B2BCustomerModel)
         {
             //Custom filter logic based on B2BUnit (Logic Removed)
             final String B2BUnitQueryString = "";
             
             final String query = res.getQuery();
             final StringBuilder queryWithFilter = new StringBuilder();
             if (StringUtils.isNotBlank(query))
             {
                 queryWithFilter.append("(").append(query).append(") AND ").append(B2BUnitQueryString);
             }
             else
             {
                 queryWithFilter.append(B2BUnitQueryString);
             }
             res.setQuery(queryWithFilter.toString());
         }
         return res;
     }
     
     /**
      * @param userService
      *           the userService to set
      */
     public void setUserService(final UserService userService)
     {
         this.userService = userService;
     }
 }
tino_kissig
Active Participant
0 Kudos

Hi Danny!

Your problem could be solved by introducing a SolrQueryPostProcessor.

For instance to show only products that are on stock:

 public class InStockSolrQueryPostProcessor implements SolrQueryPostProcessor
 {
     @Override
     public SolrQuery process(final SolrQuery solrQuery, final SearchQuery searchQuery)
     {
         solrQuery.addFilterQuery("inStockFlag_boolean:true");
         return solrQuery;
     }
 }


Former Member
0 Kudos

Thanks, that is a really nice solution. I missed that one!

sundar137
Discoverer
0 Kudos

Hi Tino, Did you get any solution for this issue. I am also facing the same issue.

Former Member
0 Kudos

Oh this is simple. Your customer's requirements are wrong. They will realise this when they come to test it for themselves on their live site.

tino_kissig
Active Participant
0 Kudos

That's a good one! That might be the "SAP" way but we prefer to deliver a perfect solution for our customers. I can't see why this requirement should be wrong.

Former Member
0 Kudos

Don't think for a second that I am anything to do with SAP

And I have found in this world that you should not give people what they ask for, you should give them what they need.

tino_kissig
Active Participant
0 Kudos

Are we still discussing our specific problem or are we already stuck in a meta discussion? Feel free to contribute here to find an appropriate answer to my question.

Former Member
0 Kudos

Hi Tino, you can extend DefaultFreeTextQueryBuilder class and replace the OR operator with AND for example . searchQuery.searchInField(field, ClientUtils.escapeQueryChars(value) + suffixOp + boost, SearchQuery.**Operator.AND**);

you get the following Query.

(field1_text_en:pants AND red) OR (field2_en_string_mv:pants AND red) OR (field3_text_en_mv:pants AND red) )

And i think its fulfill your requirement.

tino_kissig
Active Participant
0 Kudos

It does definitely not fulfill our requirements. If you think of just 2 indexed fields "color" and "name" and the customer searches for "red pants" then we only want to find documents having "red" as a color and "pants" in the name attribute. Your solution would only find documents having both terms in one of the fields. In my example it would find zero documents.

0 Kudos

Please see:

https://experts.hybris.com/questions/4089/making-use-of-the-extendeddismax-for-solr-searches.html

I think you could make use of the edismax that supports lucene like queries out of the box. The only problem is, that hybris does not support this right out of the box.

We are currently working on introducing this in our project and I was asking if there are already experiences with it.

tino_kissig
Active Participant
0 Kudos

Hi Stefan! Thanks for your reply.

As far as I can see hybris already uses edismax since this is set in the request to the Solr server via defType=edismax.

As already mentioned in my initial question we think that the API of de.hybris.platform.solrfacetsearch.search.SearchQuery just doesn't allow to create the query we want...