Skip to main content

Search records in salesforce using SOSL query

How to build a custom search page to fetch records dynamically.

Here I have built custom search on a custom object called KnowledgeArticle__c

Controller:

public with sharing class KBASearchController{
     private Integer OffsetSize = 0;
     private Integer QueryLimit = 200;
     private Integer CountTotalRecords{get;set;}
     public string globalSearch{get;set;}
     private id  Articlename{set;get;}
     private static List<KnowledgeArticle__c> outputRecords;
     public PageReference ViewData() {
        return runSearch();
    }
    public pagereference doGlobalsearch(){
     
        if(globalSearch==null || globalSearch==''){
            ApexPages.addMessage(new ApexPages.Message(ApexPages.SEVERITY.ERROR,'Please enter global search criteria to search the results'));
            return null;
        }
        if(globalSearch!=null && globalSearch!='')
        {
              outputRecords=null;
            List<Sobject[]> articleResult= [FIND :globalSearch IN ALL FIELDS RETURNING KnowledgeArticle__c(Name,Keywords__c,LastModifiedDate,Account__c,Question__c,
                                            Article_Type__c,Accounts__c,Title__c,Version__c,Article_Submitter__c,PublishedDate__c,Relevance__c,
                                            KBA_Rating__c,Status__c,Source__c,Author__c,FKCategory__r.Id,Answer__c,FKCategory__c where (Status__c=:publishedStatus or Status__c=:inReviewStatus) order by createdDate, KBA_Rating__c desc limit 500) ];
           if(articleResult.size()>0 && articleResult[0].size()>0)
           {
               outputRecords=(List<KnowledgeArticle__c>)articleResult[0];
           }
        }
        return null;
     
 
 
    }
    public PageReference resetFilterSec() {
        QueryLimit =500;
        expressionquery=sortExpression+' ' +sortDirection + ' limit :QueryLimit';
        outputRecords = [select Name,Keywords__c,LastModifiedDate,Account__c ,
                        Question__c,Article_Type__c,Accounts__c,Title__c,Author__c,
                    Version__c,Article_Submitter__c,PublishedDate__c,FKCategory__r.Id,Relevance__c,Status__c,KBA_Rating__c,
                    Source__c,Answer__c,FKCategory__c from KnowledgeArticle__c
                    where Name!= null and (Status__c=:publishedStatus or Status__c=:inReviewStatus) order by createdDate, KBA_Rating__c desc Limit 200];
                    articleRec=new KnowledgeArticle__c();
                    globalSearch='';
        return null;
    }
    private string expressionquery;
    private String sortDirection = 'ASC';
    private String sortExp= 'createdDate';
    public String sortExpression
   {
     get
     {
        return sortExp;
     }
     set
     {
       //if the column is clicked on then switch between Ascending and Descending modes
       if (value == sortExp)
         sortDirection = (sortDirection == 'ASC')? 'DESC' : 'ASC';
       else
         sortDirection = 'ASC';
       sortExp = value;
     }
   }

 public String getSortDirection()
 {
    //if not column is selected
    if (sortExpression == null || sortExpression == '')
      return 'ASC';
    else
     return sortDirection;
 }

 public void setSortDirection(String value)
 {
   sortDirection = value;
 }


    private String soql {get;set;}
    public KnowledgeArticle__c articleRec{get;set;}
    public id ID {get; set;}
 
    public List<KnowledgeArticle__c> getkbaList(){
        return outputRecords;
    }
 
    String publishedStatus = 'Published';
    String inReviewStatus = 'In Review';
   //public Integer CountTotalRecords{get;set;}
    //public Integer OffsetSize = 0;
    //private Integer QueryLimit = 5;
    public string query{get;set;}
    public KBASearchController() {
        QueryLimit =500;
        query='select Name,Keywords__c,LastModifiedDate,Account__c,   Question__c,Article_Type__c,Accounts__c,Title__c,'+
                   ' Version__c,Article_Submitter__c,PublishedDate__c,FKCategory__r.Id,Relevance__c,KBA_Rating__c,Status__c,Source__c,Author__c,Answer__c,FKCategory__c'+
                   ' from KnowledgeArticle__c ';
         expressionquery=' order by '+sortExpression+' ' +sortDirection + ' limit :QueryLimit';
         expressionquery=' order by createdDate, KBA_Rating__c desc limit 500';
        system.debug('query + expressionquery============='+(query + ' '+expressionquery));    
        outputRecords = database.query(query + 'where Name!= null and (Status__c=:publishedStatus or Status__c=:inReviewStatus)' +expressionquery);
        CountTotalRecords=[select count() from KnowledgeArticle__c ];
                    articleRec=new KnowledgeArticle__c();
             
    }
 
 
 
    public string myquery{get;set;}
    String accountFiltersSet='';
    public PageReference runSearch() {      
        QueryLimit =500;
        Boolean includeResult=true;
        // there would be AND operator
       system.debug('Test Knowledge Article *****'+articleRec);
       if(articleRec.Accounts__c!=null){
        string accountFilter=articleRec.Accounts__c;
        system.debug('ACCFIL'+accountFilter);
        accountFilter=accountFilter.replace('[','');
        accountFilter=accountFilter.replace(']','');
     
        Boolean conditionRun=false;
        myquery=query;
        for(string s:accountFilter.split(',')){
            accountFiltersSet=
            + '\''+s.tolowerCase().trim()+'\',';
        }
     
        accountFiltersSet=accountFiltersSet!=''?accountFiltersSet.substring(0,accountFiltersSet.lastIndexOf(',')):'';}
     
     
        string whereClause=' where Name!= null and (Status__c=:publishedStatus or Status__c=:inReviewStatus) ';
     
     
 
     
        Boolean runSOSL=false;
        string soslsearchFilter='';
     
        system.debug('---Keywords----'+articleRec.Keywords__c);
        if(articleRec.Keywords__c!=null && articleRec.Keywords__c!='')
                soslsearchFilter=articleRec.Keywords__c;
        if(articleRec.Question__c!=null && articleRec.Question__c!=''){
            soslsearchFilter=soslsearchFilter!=''?soslsearchFilter+' AND '+articleRec.Question__c:articleRec.Question__c;
        }
        if(articleRec.Answer__c!=null && articleRec.Answer__c!=''){
            soslsearchFilter=soslsearchFilter!=''?soslsearchFilter+' AND '+articleRec.Answer__c:articleRec.Answer__c;
        }
     
        system.debug(runSOSL +'===='+soslsearchFilter);
        if(articleRec.Title__c!=null && articleRec.Title__c!=''){
            whereClause+=' and Title__c like \'%'+articleRec.Title__c+'%\'';
        }
        if(articleRec.Author__c!=null && articleRec.Author__c!=''){
            whereClause+=' and Author__c like \'%'+articleRec.Author__c+'%\'';
        }
        if(articleRec.Name!=null && articleRec.Name!=''){
            whereClause+=' and Name like \'%'+articleRec.Name+'%\'';
        }
        system.debug('---cat----'+articleRec.FKCategory__c);
        if(articleRec.FKCategory__c!=null){
            whereClause+=' and FKCategory__c =\''+articleRec.FKCategory__c+'\'';
        }  
        system.debug('articleRec.Accounts__c----------'+articleRec.Accounts__c);
        if(articleRec.Accounts__c!=null && articleRec.Accounts__c!='' && articleRec.Accounts__c!='[]' && accountFiltersSet!=''){
            whereClause+=' and Accounts__c in ('+ accountFiltersSet +')';
            //'\''+articleRec.Accounts__c+'\'';
        }
        string query;
        system.debug('######'+soslsearchFilter);
     
        if(soslsearchFilter!=''){
            query='FIND :soslsearchFilter IN ALL FIELDS RETURNING KnowledgeArticle__c'+
            '(Name,Keywords__c,LastModifiedDate,Account__c,Question__c,'+
             'Article_Type__c,Accounts__c,Title__c,Version__c,Article_Submitter__c,PublishedDate__c,'+
             'Relevance__c,KBA_Rating__c,Status__c,Source__c,FKCategory__c,Author__c,Answer__c '+ whereClause+
             ' order by createdDate, KBA_Rating__c desc limit 500)';
            List<Sobject[]> articleResult= search.query(query);
               system.debug('!!!!'+query);
              system.debug('####'+articleResult);
            if(articleResult.size()>0 && articleResult[0].size()>0){
               outputRecords=(List<KnowledgeArticle__c>)articleResult[0];
        }
        }else{
            system.debug('run in soql '+myquery + whereClause+' order by createdDate, KBA_Rating__c desc limit 500');
            //Ramya
            if(myquery !=null){
            //
            outputRecords=database.query(myquery + whereClause);
            }
        }
     
     
           system.debug('account fitler is '+accountFiltersSet);
       
         /*myquery+= ' order by '+sortExpression+' ' +sortDirection + ' limit :QueryLimit';
        outputRecords=new List<KnowledgeArticle__c>();
        system.debug('myquery============='+myquery);
        integer counter=0;
        for(KnowledgeArticle__c article:database.query(myquery)){
            includeResult=false;
            if(counter==500)
            break;
            system.debug('article query'+article);
             system.debug('account fitler is '+accountFiltersSet);
             system.debug('----articleRec--search------'+articleRec);
            if(articleRec.Keywords__c!=null && articleRec.Keywords__c!=''){
                includeResult=article.Keywords__c!=null && article.Keywords__c.toLowerCase().contains(articleRec.Keywords__c.toLowerCase())?true:false;
                if(!includeResult)continue;
            }
            if(articleRec.Title__c!=null && articleRec.Title__c!=''){
                includeResult=article.Title__c!=null && article.Title__c.toLowerCase().contains(articleRec.Title__c.toLowerCase())?true:false;
                system.debug('in case of title'+includeResult+'----'+article.Title__c);
                if(!includeResult)continue;
            }
            if(articleRec.Question__c!=null && articleRec.Question__c!=''){
                includeResult=article.Question__c!=null && article.Question__c.toLowerCase().contains(articleRec.Question__c.toLowerCase())?true:false;
                if(!includeResult)continue;
            }
            if(articleRec.Answer__c!=null && articleRec.Answer__c!=''){
                includeResult=article.Answer__c!=null && article.Answer__c.toLowerCase().contains(articleRec.Answer__c.toLowerCase())?true:false;
                if(!includeResult)continue;
            }
            if(articleRec.Author__c!=null && articleRec.Author__c!=''){
                includeResult=article.Author__c!=null && article.Author__c.toLowerCase().contains(articleRec.Author__c.toLowerCase())?true:false;
                if(!includeResult)continue;
            }
         
            if(articleRec.Name!=null && articleRec.Name!='' && articleRec.Name!='--None--'){
                includeResult=article.Name!=null && article.Name.toLowerCase().contains(articleRec.Name.toLowerCase())?true:false;
                if(!includeResult)continue;
            }
            if(articleRec.Module__c!=null && articleRec.Module__c!='' && articleRec.Module__c!='--None--'){
                system.debug('in account');
                includeResult=article.Module__c!=null && article.Module__c.toLowerCase().contains(articleRec.Module__c.toLowerCase())?true:false;
                system.debug('in module boolean'+includeResult);
                if(!includeResult)continue;
            }
            system.debug('after source'+includeResult+'=====#####====='+articleRec.Accounts__c+'+++++++++');
            if(articleRec.Accounts__c!=null && articleRec.Accounts__c!='' && articleRec.Accounts__c!='--None--' && articleRec.Accounts__c!='[]'){
                system.debug('in account'+articleRec.Accounts__c+'asdfdasfsdf');
                includeResult=article.Account__c!=null && accountFiltersSet.contains(article.Account__c.toLowerCase())?true:false;
                system.debug('in account boolean'+includeResult);
                if(!includeResult)continue;
            }
            system.debug('after source'+includeResult);
            system.debug('includeResult'+includeResult);
            if(includeResult && counter<500){
                counter++;
                outputRecords.add(article);
            }
         
        }*/
       // system.debug('outputRecords'+outputRecords.size());
        return null;
     
    }
    public pageReference displayKA(){
        ID = ApexPages.CurrentPage().getParameters().get('Articlename');
      //system.debug('#########'+name);
       pagereference pr = new Pagereference('/apex/KBA_Feedback?id='+Articlename);
      pr.setredirect(true);
       return pr;
   
    }
 
    public List<selectOption> getaccountList()
    {
        List<selectOption> accountList = new List<selectoption>();
        Schema.DescribeFieldResult field = KnowledgeArticle__c.Accounts__c.getDescribe();

         for (Schema.PicklistEntry f : field.getPicklistValues())
          accountList.add(new selectoption(f.getLabel(),f.getLabel()));

      return accountList;        
    }

  /*public List<String> moduleList{
    get {
      if (moduleList == null) {

        moduleList = new List<String>();
        Schema.DescribeFieldResult field = KnowledgeArticle__c.Module__c.getDescribe();

        for (Schema.PicklistEntry f : field.getPicklistValues())
          moduleList.add(f.getLabel());

      }
      return moduleList;        
    }
    set;
  }*/


 
 /*
 public Boolean getDisablePrevious(){
        if(OffsetSize>0){
            return false;
        }
        else return true;
    }

    public Boolean getDisableNext() {
        if (OffsetSize + QueryLimit < countTotalRecords){
            return false;
        }
        else return true;
    }

    public PageReference Next() {
        OffsetSize += QueryLimit;
        return runSearch();
    }

    public PageReference Previous() {
        OffsetSize -= QueryLimit;
        return runSearch();
    }
  */
}

-----------------------------------------------------------------
Visualforce Page:

<apex:page controller="KBASearchController" sidebar="false">

  <apex:form id="theForm">

  <apex:pageMessages id="errors" />
  <style>
    .scroll {
   width: 100%; height: 1000px;
   overflow: scroll;
}
</style>
  <apex:pageBlock title="Welcome to Knowledge Article Search" mode="edit">


  <table width="100%" border="0">
  <tr>
      <td colspan="2" style="font-weight:bold;" align="right">
   
             <table>
                 <tr> <td> <b>Global Search</b> &nbsp;&nbsp;  <apex:inputText value="{!globalSearch}" onkeypress="return noglobalsearchenter(event);"/></td> </tr>
                   <tr> <td align="center">
                   <apex:actionStatus id="status2">
                    <apex:facet name="start">
                     <apex:outputPanel >
                          <apex:commandButton disabled="true" value="Search" />
                         <apex:commandButton disabled="true" value="Reset Values" />
                         <apex:outputText value="Searching...." style="font-weight:bold;"/>
                         <apex:image value="/img/loading32.gif" style="height: 20px;"/>
                    </apex:outputPanel>
                    </apex:facet>
                     <apex:facet name="stop">
                      <apex:outputPanel >
                          <apex:commandButton action="{!doGlobalsearch}" value="Search" reRender="theForm" status="status2"/>
                  <apex:commandButton value="Reset Values" action="{!resetFilterSec}" reRender="theForm" status="status2"/>
                        </apex:outputPanel>
                    </apex:facet>
              </apex:actionStatus> </td> </tr>
           
             </table>
         
            </td>
 
   
  </tr>
  <tr>
    <td width="200" valign="top">

      <apex:pageBlock title="Filter" mode="edit" id="criteria">
 

     <table cellpadding="2" cellspacing="2">
      <tr>
        <td style="font-weight:bold;">Keywords<br/>
        <apex:inputText value="{!articleRec.Keywords__c}" onkeypress="return noenter(event);"/>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Title<br/>
        <apex:inputField value="{!articleRec.Title__c}" required="false" onkeypress="return noenter(event);"/>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Question<br/>
        <apex:inputText value="{!articleRec.Question__c}" onkeypress="return noenter(event);"/>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Answer<br/>
         <apex:inputText value="{!articleRec.Answer__c}" onkeypress="return noenter(event);"/>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Owner<br/>
        <apex:inputField value="{!articleRec.Author__c}" onkeypress="return noenter(event);"/>
        </td>
      </tr>
      <tr>
       <td style="font-weight:bold;">Category<br/>
        <apex:inputField value="{!articleRec.FKCategory__c}" onkeypress="return noenter(event);"/>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Account<br/>
        <apex:selectList value="{!articleRec.Accounts__c}" multiselect="true" size="4" style="width:150px;" >
            <apex:selectOptions value="{!accountList}"/>
        </apex:selectList>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Article ID<br/>
        <apex:inputText value="{!articleRec.Name}" onkeypress="return noenter(event);"/>
        </td>
      </tr>
   
      <tr>
          <td>
             

              <apex:actionStatus id="status">
                    <apex:facet name="start">
                     <apex:outputPanel >
                          <apex:commandButton disabled="true" value="Search" />
                         <apex:commandButton disabled="true" value="Reset Values" />
                         <apex:outputText value="Searching...." style="font-weight:bold;"/>
                         <apex:image value="/img/loading32.gif" style="height: 20px;"/>
                    </apex:outputPanel>
                    </apex:facet>
                     <apex:facet name="stop">
                      <apex:outputPanel >
                          <apex:commandButton reRender="theForm" action="{!runSearch}" value="Search"  status="status"/>
                  <apex:commandButton value="Reset Values" action="{!resetFilterSec}" reRender="theForm" status="status"/>
                        </apex:outputPanel>
                    </apex:facet>
              </apex:actionStatus>
          </td>
      </tr>
      </table>
      </apex:pageBlock>

    </td>
    <td valign="top">

        <apex:pageBlock mode="edit" id="results">
     
            <div class="scroll">
            <apex:outputText value="No Articles Found" style="font-weight:bold;font-size:15px;font-color:red" rendered="{!kbaList==null}"/>
            <apex:pageBlockTable value="{!kbaList}" var="kba" id="pbtableid" rendered="{!kbaList!=null}">
                 <apex:column headerValue="Action" >
                        <apex:outputLink value="{!URLFOR($Action.KM_KnowledgeArticle__c.Edit, kba.id)}"  target="_blank">Edit</apex:outputLink>
                </apex:column>
                <apex:column headerValue="Article Id">
                  <!-- <apex:facet name="header">
                  {!IF(sortExpression=='Name',IF(sortDirection='ASC','▼','▲'),'')}
               
                       <apex:commandLink value="Article Id" id="articleName" action="{!runSearch}" reRender="results">
                                 <apex:param value="Name" name="Name" assignTo="{!sortExpression}"/>
                       </apex:commandLink>
                  </apex:facet>
                <apex:commandLink id="commandLink"  action="{!displayKA}" value="{!kba.Name}" target="_blank" >
                            <apex:param name="Articlename" value="{!kba.id}" />
                </apex:commandLink>-->
                                  <a href="/apex/KBA_Feedback?id={!kba.id}" target="_blank">{!kba.name} </a>

              </apex:column>
           
              <apex:column >
                 <apex:facet name="header">
                     <apex:commandLink value="Article Type{!IF(sortExpression=='Article_Type__c',IF(sortDirection='ASC','▼','▲'),'')}" id="articleType" action="{!runSearch}" reRender="results">
                                         <apex:param value="Article_Type__c" name="Article_Type__c" assignTo="{!sortExpression}"/>
                      </apex:commandLink>
                  </apex:facet>
                <apex:outputText value="{!kba.Article_Type__c}"/>
              </apex:column>
           
              <apex:column >
                    <apex:facet name="header">
                         <apex:commandLink value="Account{!IF(sortExpression=='Accounts__c',IF(sortDirection='ASC','▼','▲'),'')}" id="articleAccount" action="{!runSearch}" reRender="results">
                                         <apex:param value="Accounts__c" name="Accounts__c" assignTo="{!sortExpression}"/>
                        </apex:commandLink>
                   
                    </apex:facet>
                    <apex:outputText value="{!kba.Accounts__c}"  />
              </apex:column>
             
                <apex:column value="{!kba.Title__c}" headerValue="Title" />
                 <!--<apex:column value="{!kba.Module__c}" headerValue="Module" />-->
                <apex:column value="{!kba.FKCategory__c}" headerValue="Category"/>
                <apex:column value="{!kba.Version__c}" headerValue="Version" />
                <apex:column value="{!kba.Article_Submitter__c}" headerValue="Article Submitter" />
                <apex:column value="{!kba.PublishedDate__c}" headerValue="Published On" />
                <apex:column value="{!kba.LastModifiedDate}" headerValue="Last Updated" />
                <apex:column value="{!kba.Source__c}"/>
               <apex:column value="{!kba.KBA_Rating__c}" headerValue="Rating" />
                <apex:column value="{!kba.Status__c }" headerValue="Status" />
             
             
            </apex:pageBlockTable>
          </div>
         
         <!-- <apex:pageBlockButtons >
                    <apex:commandButton value="Previous" action="{!Previous}" rerender="theForm"    status="status,status2" disabled="{!DisablePrevious}" />
                    <apex:commandButton value="Next" action="{!Next}" reRender="theForm"     status="status,status2" disabled="{!DisableNext}" />
                    <apex:actionStatus id="status" startText="Please Wait getting results ..."/>
                </apex:pageBlockButtons>-->

        </apex:pageBlock>

    </td>
  </tr>
  </table>

  </apex:pageBlock>
        <apex:actionFunction name="doSearchArticle" action="{!runSearch}" status="status" reRender="theForm" />
         <apex:actionFunction name="doGlobalsearch" action="{!doGlobalsearch}" status="status2" reRender="theForm" />
     
  </apex:form>
  <script type='text/javascript'>
    function noenter(ev)  {
        if (window.event && window.event.keyCode == 13 || ev.which == 13) {
            doSearchArticle();
            return false;
         } else {
              return true;
         }
     }
   
     function noglobalsearchenter(ev)
     {
          if (window.event && window.event.keyCode == 13 || ev.which == 13) {
            doGlobalsearch();
            return false;
         } else {
              return true;
         }
   
     }
</script>


</apex:page>

Comments

Popular posts from this blog

Track Field History for more than 20 fields - Salesforce

All of us would have come across a situation when we need to track more than 20 fields for an object in salesforce. We have raised this Idea around 8 years ago in the success community. But sill it has't implemented by salesforce. But for now, we can achieve it partially with the following workaround. Approach: This approach uses a custom Text field which stores values of multiple other individual fields. Then enabling field history tracking of this field would allow you to track changes for multiple sets of other individual fields. Thus even though remaining within the count limit 20, yet track changes of more than 20 fields. Let us in this example take “Account ”  object and apply the steps to track change in Account Name, Phone, Parent Account and Billing Address all together. Steps: Step 1:  Add a new custom field. Setup -> Customize -> Accounts -> Fields Create a new Text (255) field “ Track FieldHistory ” (Or give any other n...

Customize the columns in the Items to Approve section on home page

We can customize the items to approve section with the help of custom visualforce page. All you need to do is create the below page with your object and respected fields to be displayed and then add the page to a new home page component. Page: <apex:page controller="itemstoApprovecontroller" sidebar="false" showHeader="false">     <apex:form >         <apex:pageBlock title="Incidents/Service Request To Approve">             <apex:pageBlockTable value="{!items_to_approve}" var="item_to_approve">                 <apex:column headerValue="Action" width="160 px" >                                     <apex:commandLink target="_top" value="Reassign |" action="{!REASSIGNnavigation}" style="text-decoration:none;color: #015ba7;" styleClass="cactionLink">   ...

Kanban view for Lightning

Tired of list views? Looking for a dynamic views to show your cases or opportunities in all new way? Here we go,  Salesforce introduced Kanban views for us to have better visibility  of our cases/opportunities and their journey from opening to closure. A case kanban allows you to visually summarize all of the cases for your agents,  by status or priority. It's not only a board, but also a  drag and drop  tool that will help agents keep their cases moving towards resolution. Similarly an opportunity Kanban display opportunities from a particular sales path Let's take a closer look at what all we can do with Kanban Track a Deal with Path Display opportunities by Sales path Move an Opportunity to the Next Stage Take Action on Your Records