RE: Grouping of search Results by Asset Type in Liferay DXP?

Stephan Neese, modified 6 Years ago. New Member Posts: 7 Join Date: 2/13/17 Recent Posts

Hello Forum,

 

a customer wants their Search Results grouped by default in the following way 

1. web contents

2. documents

3. everything else (order does not matter here)

Since this should be sorted by default a facet wont do it here. I wanted to implement this using an IndexerPostProcessor and by setting a GroupBy Object in the SearchContext in the Processors Method postProcessFullQuery(). However even though the method is definitely called and the GroupBy Object is set in the SearchContext (I put a breakpoint in there) the search seems to ignore my GroupBy argument as the Order of the Results shown is not affected. As you can see in the code below I have tried to setup a very basic GroupBy Argument (I just added a max size of 5 to quicktest my solution). Just Telling LR by which Field to group. No Sort order or anything yet. Do I need to tell LR by which order I want to Sort the Field for it to work or activate the groupby somewhere? Has anyone experience with this? Thank you.

Code:

 

@Component(
   immediate = true,
   property = {
      "indexer.class.name=com.liferay.journal.model.JournalArticle",
      "indexer.class.name=com.liferay.portlet.documentlibrary.model.DLFileEntry"
   },
   service = IndexerPostProcessor.class
)
public class MultipleEntityIndexerPostProcessor
   implements IndexerPostProcessor {

   @Override
   public void postProcessContextBooleanFilter(
         BooleanFilter booleanFilter, SearchContext searchContext)
      throws Exception {

   }

   @Override
   public void postProcessContextQuery(
         BooleanQuery contextQuery, SearchContext searchContext)
      throws Exception {

   }

   @Override
   public void postProcessDocument(Document document, Object obj)
      throws Exception {

   }

   @Override
   public void postProcessFullQuery(
         BooleanQuery fullQuery, SearchContext searchContext)
      throws Exception {
      searchContext.setGroupBy(createGroupBy());
   }

   @Override
   public void postProcessSearchQuery(
         BooleanQuery searchQuery, BooleanFilter booleanFilter,
         SearchContext searchContext)
      throws Exception {

   }

   @Override
   public void postProcessSearchQuery(
         BooleanQuery searchQuery, SearchContext searchContext)
      throws Exception {

   }

   @Override
   public void postProcessSummary(
      Summary summary, Document document, Locale locale, String snippet) {

   }

   private GroupBy createGroupBy(){
      GroupBy groupBy = new GroupBy("entryClassName");
      groupBy.setSize(5);
      return groupBy;
   }
}
Jamie Sammons, modified 6 Years ago. New Member Posts: 7 Join Date: 2/13/17 Recent Posts
Hi Everyone,

I found a pointer to a possible solution. Elastic Search for example has the so called "function_score" method. This allows you to modify the score of elements. Here is an example: 

"function_score" : {
            "query": {
                "match": { "title": "hello world" }
            },
            "functions": [
                {
                    "filter" : { "match": { "entryClassName": "com.liferay.journal.model.JournalArticle" } },
                    "weight" : 10
                },
                {
                    "filter" : { "match": { "entryClassName": "com.liferay.portlet.documentlibrary.model.DLFileEntry" } },
                    "weight" : 5
                }
            ],
            "boost_mode": "sum"
        }

In this example we add 10 to the score if we have a journal article and 5 if DLFileEntry. My question now is. How do you implement this in the search. How do you need to manipulate the query in Liferay?

best regards

​​​​​​​Stephan
thumbnail
Narsingh Pal, modified 5 Years ago. Junior Member Posts: 53 Join Date: 1/18/14 Recent Posts
Hi Stephan,

Were you able to find solution for this ?

Thanks and RegardsNarsingh Pal
thumbnail
Gaurav Jain, modified 5 Years ago. Junior Member Posts: 85 Join Date: 7/12/16 Recent Posts
Hi Narsingh Pal,
For your requirement, you can also try Boosting, please have a look at following example:
String className = PortalUtil.getClassName(classNameId);
 BooleanQuery assetEntryQuery = new BooleanQueryImpl();
  assetEntryQuery.addTerm(Field.ENTRY_CLASS_NAME, className);
  float boost = 5.0;
  assetEntryQuery.setBoost(boost);

And use this query further......
For each classname different boost level can be set as per the requirement, Higher boost level entities will be on higher orders.
One more thing you need to do 
Sort[] sorts = new Sort[]{new Sort ("_score", Sort.SCORE_TYPE, false)};
searchContext.setSorts(sorts);
Gopal Prasad Satapathy, modified 5 Years ago. Junior Member Posts: 51 Join Date: 3/29/18 Recent Posts
Hello Gaurav,
My  intention is to sort the search result 1st based on the site and then based on  asset type. Is there any working example code that you can share for reference?

Thanks,
Gopal