Using the GetSearchTermAssociation service to bypass Solr synonym expansion in HCL Commerce search

You can use the GetSearchTermAssociation service in HCL Commerce search to evaluate synonyms and replacements, instead of using the default Solr synonym and replacement expansion implementation. For example, these are the steps to change the basic store search in the Madisons starter store to use the GetSearchTermAssociation service in HCL Commerce search to expand synonyms, instead of using the default Solr synonym expansion implementation, SynonymFilterFactory.

Before you begin

Create a new Java search expression provider class that expands a search term into its synonyms. The following downloadable sample code (SolrSearchTermAssociationExpressionProvider.java) can be used as a reference:

Procedure

  1. Open HCL Commerce Developer and switch to the Enterprise Explorer view.
  2. Create a new folder for your customized HCL Commerce search component configuration file:
    1. Navigate to the following path:

      workspace_dir\WC\xml\config\

    2. In the config folder, add a new com.ibm.commece.catalog-ext folder so the path looks like this:

      workspace_dir\WC\xml\config\com.ibm.commece.catalog-ext\

      If this folder already exists and it contains a customized version of the wc-search.xml file, then open the file and skip to step 6.

  3. Navigate to the following path:

    workspace_dir\WC\xml\config\com.ibm.commerce.catalog-fep\

  4. Copy the wc-search.xml file to the new com.ibm.commece.catalog-ext folder you created in the first step.
  5. Open the copied wc-search.xml file in an editor and delete everything except the following lines, to get the customized version of the wc-search.xml file:
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <_config:search-config
    xmlns:_config="http://www.ibm.com/xmlns/prod/commerce/foundation/config"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com/xmlns/prod/commerce/foundation/config ../xsd/wc-search.xsd ">
    
    
    </_config:search-config> 
    
  6. Add the following new profiles to the custom wc-search.xml, within the <_config:search-config> element:
    
    <_config:profile extends="IBM_findCatalogEntryByNameAndShortDescription" name="X_findCatalogEntryByNameAndShortDescription"  >
           <_config:query inherits="false">
                <_config:param name="maxRows" value="500"/>
                <_config:param name="maxTimeAllowed" value="3000"/>
                <_config:param name="debug" value="false"/>
                <_config:param name="preview" value="2"/>
                
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchProfileNameValidator"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchIndexNameValidator"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchIndexSynchronizer"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchBasedMerchandisingExpressionProvider"/>
                
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchTermAssociationExpressionProvider"/>
                
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByKeywordExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByCategoryExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByManufacturerExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByPriceExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByFacetExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByStorePathExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchByCustomExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchFacetConditionExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchTypeExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchMetaTokenExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchProductEntitlementExpressionProvider"/>
                <_config:provider classname="com.ibm.commerce.catalog.facade.server.services.search.expression.solr.SolrSearchExpressionValidator"/>
                
                <_config:field name="name"/>
                <_config:field name="defaultSearch"/>
                <_config:field name="shortDescription"/>
                <_config:field name="unstructure"/>
            </_config:query>
      </_config:profile>
      
      <_config:profile extends="X_findCatalogEntryByNameAndShortDescription" name="X_findCatalogEntryByNameAndShortDescriptionInDetail"/>
    
  7. Save and close the customized file.
  8. To use the new profiles in the Madisons starter store:
    1. Open the following file in an editor
      • WC_eardir\Stores.war\WebContent\Madisons\Snippets\Search\SearchSetup.jspf
    2. Replace the following snippet:
      
      <c:set var="searchProfile" value="IBM_findCatalogEntryByNameAndShortDescription" scope="request"/> 
      
      With this snippet:
      
      <c:set var="searchProfile" value="X_findCatalogEntryByNameAndShortDescription" scope="request"/> 
      
    3. Replace the following snippet:
       
      <c:when test="${pageView == 'detailed' and searchProfile == 'IBM_findCatalogEntryByNameAndShortDescription'}">
      <c:set var="navigationView" value="getCatalogNavigationView" scope="request"/>
      <c:set var="searchProfile" value="IBM_findCatalogEntryByNameAndShortDescriptionInDetail" scope="request"/>
      </c:when> 
      
      With this snippet:
      
      <c:when test="${pageView == 'detailed' and searchProfile == 'X_findCatalogEntryByNameAndShortDescription'}">
      <c:set var="navigationView" value="getCatalogNavigationView" scope="request"/>
      <c:set var="searchProfile" value="X_findCatalogEntryByNameAndShortDescriptionInDetail" scope="request"/>
      </c:when> 
      
    4. Save and close the file.
  9. The sample expression provider only expands synonyms. If it is modified to also handle replacements, the Solr synonyms.txt file is no longer needed. In that case, you can modify the Management Center configuration to no longer call the PostSave PublishSearchTermAssociations service. This can be done by commenting out the following section in WC_eardir\LOBTools.war\WebContent\config\commerce\catalog\objectDefinitions\SearchTermAssociationsPrimaryObjectDefinition.def as shown below:
    
    <!--
    <PostSaveService url="/cmc/PublishSearchTermAssociations">
    <ServiceParam name="storeId"/>
    </PostSaveService>
    --> 
    
  10. Comment out the SynonymFilterFactory filter for all the HCL Commerce fields defined in schema.xml for each core. For example, in solrhome\MC_10101\en_US\CatalogEntry\conf\schema.xml, in bold:
    
    <fieldType name="wc_text" class="solr.TextField" positionIncrementGap="100">
          <analyzer type="index">
            <tokenizer class="solr.WhitespaceTokenizerFactory"/>
            <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
            <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
            <filter class="solr.LowerCaseFilterFactory"/>
            <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt" />
            <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
          </analyzer>
          <analyzer type="query">
            <tokenizer class="solr.WhitespaceTokenizerFactory"/>
            <!-- <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> -->
            <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
            <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
            <filter class="solr.LowerCaseFilterFactory"/>
            <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt" />
            <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
          </analyzer>
        </fieldType>
       
        <!-- Spell checking text field -->
        <fieldType name="wc_textSpell" class="solr.TextField" positionIncrementGap="100">
      		<analyzer type="index">
        		<tokenizer class="solr.StandardTokenizerFactory"/>
        		<filter class="solr.LowerCaseFilterFactory"/>
        		<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
        		<filter class="solr.StandardFilterFactory"/>
        		<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
      		</analyzer>
      		<analyzer type="query">
        		<tokenizer class="solr.StandardTokenizerFactory"/>
        		<filter class="solr.LowerCaseFilterFactory"/>
        		<!-- <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> -->
        		<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
        		<filter class="solr.StandardFilterFactory"/>
        		<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
      		</analyzer>
    </fieldType>