Class SolrHelperServiceImpl

java.lang.Object
org.broadleafcommerce.core.search.service.solr.SolrHelperServiceImpl
All Implemented Interfaces:
SolrHelperService

@Service("blSolrHelperService") public class SolrHelperServiceImpl extends Object implements SolrHelperService
Provides utility methods that are used by other Solr service classes
Author:
Andre Azzolini (apazzolini)
  • Field Details

  • Constructor Details

    • SolrHelperServiceImpl

      public SolrHelperServiceImpl()
  • Method Details

    • swapActiveCores

      public void swapActiveCores(SolrConfiguration solrConfiguration) throws ServiceException
      This should only ever be called when using the Solr reindex service to do a full reindex.
      Specified by:
      swapActiveCores in interface SolrHelperService
      Throws:
      SecurityException
      NoSuchFieldException
      IllegalAccessException
      IllegalArgumentException
      ServiceException
    • aliasCollectionMap

      protected Map<String,String> aliasCollectionMap(org.apache.solr.client.solrj.impl.CloudSolrClient client) throws org.apache.solr.client.solrj.SolrServerException, IOException
      Throws:
      org.apache.solr.client.solrj.SolrServerException
      IOException
    • getGlobalFacetTagField

      public String getGlobalFacetTagField()
      Description copied from interface: SolrHelperService
      This property is needed to be non-null to allow filtering by multiple facets at one time and have the results be an AND of the facets. Apart from being non-empty, the actual value does not matter.
      Specified by:
      getGlobalFacetTagField in interface SolrHelperService
      Returns:
      the non-empty global facet tag field
    • getPropertyNameForIndexField

      public String getPropertyNameForIndexField(IndexField field, FieldType fieldType, String prefix)
      Description copied from interface: SolrHelperService
      Returns the property name for the given field, field type, and prefix
      Specified by:
      getPropertyNameForIndexField in interface SolrHelperService
      Returns:
      the property name for the field and fieldtype
    • getPropertyNameForIndexField

      public String getPropertyNameForIndexField(IndexField field, FieldType searchableFieldType)
      Description copied from interface: SolrHelperService
      Returns the property name for the given field and field type. This will apply the global prefix to the field, and it will also apply either the locale prefix or the pricelist prefix, depending on whether or not the field type was set to FieldType.PRICE
      Specified by:
      getPropertyNameForIndexField in interface SolrHelperService
      Returns:
      the property name for the field and fieldtype
    • convertPrefixListToString

      protected String convertPrefixListToString(List<String> prefixList)
    • getCategoryId

      public Long getCategoryId(Category category)
      Description copied from interface: SolrHelperService
      In certain cases, the category id used for Solr indexing is different than the direct id on the product. This method provides a hook to substitute the category id if necessary.
      Specified by:
      getCategoryId in interface SolrHelperService
      Returns:
      the category id to use
    • getCategoryId

      public Long getCategoryId(Long category)
      Description copied from interface: SolrHelperService
      In certain cases, the category id used for Solr indexing is different than the direct id on the product. This method provides a hook to substitute the category id if necessary.
      Specified by:
      getCategoryId in interface SolrHelperService
      Returns:
      the category id to use
    • getIndexableId

      public Long getIndexableId(Indexable indexable)
      Description copied from interface: SolrHelperService
      In certain cases, the sku id used for Solr indexing is different than the direct id on the sku. This method provides a hook to substitute the sku id if necessary.
      Specified by:
      getIndexableId in interface SolrHelperService
      Returns:
      the sku id to use
    • getPrimaryDocumentType

      public String getPrimaryDocumentType()
      Specified by:
      getPrimaryDocumentType in interface SolrHelperService
      Returns:
      the type of the primary indexable document
    • getCurrentProductId

      public Long getCurrentProductId(Indexable indexable)
      Specified by:
      getCurrentProductId in interface SolrHelperService
    • getProductForIndexable

      public Product getProductForIndexable(Indexable indexable)
      Specified by:
      getProductForIndexable in interface SolrHelperService
    • getTypeFieldName

      public String getTypeFieldName()
      Description copied from interface: SolrHelperService
      Returns the type field name, usually 'type_s'
      Specified by:
      getTypeFieldName in interface SolrHelperService
      Returns:
    • getDocumentType

      public String getDocumentType(Indexable indexable)
      Description copied from interface: SolrHelperService
      Returns the type for the given Indexable. For Product's this is "product".
      Specified by:
      getDocumentType in interface SolrHelperService
      Returns:
    • getSolrDocumentId

      public String getSolrDocumentId(org.apache.solr.common.SolrInputDocument document, Indexable indexable)
      Specified by:
      getSolrDocumentId in interface SolrHelperService
      Returns:
      the Solr id of this indexable
    • getNamespaceFieldName

      public String getNamespaceFieldName()
      Specified by:
      getNamespaceFieldName in interface SolrHelperService
      Returns:
      the name of the field that keeps track what namespace this document belongs to
    • getIdFieldName

      public String getIdFieldName()
      Specified by:
      getIdFieldName in interface SolrHelperService
      Returns:
      the id field name, with the global prefix as appropriate
    • getIndexableIdFieldName

      public String getIndexableIdFieldName()
      Specified by:
      getIndexableIdFieldName in interface SolrHelperService
      Returns:
      the id field name. Usually "productId"
    • getCategoryFieldName

      public String getCategoryFieldName()
      Specified by:
      getCategoryFieldName in interface SolrHelperService
      Returns:
      the category field name, with the global prefix as appropriate
    • getExplicitCategoryFieldName

      public String getExplicitCategoryFieldName()
      Specified by:
      getExplicitCategoryFieldName in interface SolrHelperService
      Returns:
      the explicit category field name, with the global prefix as appropriate
    • getCatalogFieldName

      public String getCatalogFieldName()
      Description copied from interface: SolrHelperService
      The field that should store which catalog the item is being indexed for
      Specified by:
      getCatalogFieldName in interface SolrHelperService
    • getCatalogOverridesFieldName

      public String getCatalogOverridesFieldName()
      Description copied from interface: SolrHelperService

      The field that the list of catalogs that have overridden this document are in. In a multitenant environment this works like so:

      1. MASTER_CATALOG exists in a template site with ID 1 and contains #getProductIdFieldName() == 5
      2. Product ID 5 is indexed in Solr with SolrHelperService.getCatalogFieldName() == 1
      3. A standard site is created whose default catalog id is 2
      4. Catalog 1 is assigned to the standard site as EDITABLE
      5. Because the standard site can edit the catalog, edits actually create a clone of the original catalog product with the changed fields. This new product that is created in the database via this process has an id of 100
      6. Solr then creates a new document with #getProductIdFieldName() == 5
      7. and SolrHelperService.getCatalogFieldName() == 2 (note that it uses the MASTER_CATALOG product ID and not the cloned id)
      8. Solr looks up the original document for SolrHelperService.getCatalogFieldName() == 1 and #getProductIdFieldName() == 5 and then adds to the list of SolrHelperService.getCatalogOverridesFieldName(), id 2.
      9. When querying Solr for a list of products within a catalog, documents whose SolrHelperService.getCatalogOverridesFieldName() contain the current catalog are filtered out.
      Specified by:
      getCatalogOverridesFieldName in interface SolrHelperService
    • getSandBoxFieldName

      public String getSandBoxFieldName()
      Description copied from interface: SolrHelperService
      The field that stores which sandbox the document is active for. Whenever a change is made to a new Solr document is created with all of the changed field values and this field set to the sandbox the change is in so that searches work when previewing but are filtered out in production.
      Specified by:
      getSandBoxFieldName in interface SolrHelperService
    • getSandBoxPriorityFieldName

      public String getSandBoxPriorityFieldName()
      Description copied from interface: SolrHelperService
      Which level of the priority tree the sandbox field is in like approval or user
      Specified by:
      getSandBoxPriorityFieldName in interface SolrHelperService
    • getSandBoxChangeTypeFieldName

      public String getSandBoxChangeTypeFieldName()
      Description copied from interface: SolrHelperService
      Used for DELETE documents that are extra documents created in a sandbox when an item is deleted. These are eventually cleaned up when deployed to production
      Specified by:
      getSandBoxChangeTypeFieldName in interface SolrHelperService
    • getCategorySortFieldName

      public String getCategorySortFieldName(Category category)
      Specified by:
      getCategorySortFieldName in interface SolrHelperService
      Returns:
      the default sort field name for this category
    • getCategorySortFieldName

      public String getCategorySortFieldName(Long categoryId)
      Specified by:
      getCategorySortFieldName in interface SolrHelperService
      Returns:
      the default sort field name for this category
    • getLocalePrefix

      public String getLocalePrefix()
      Description copied from interface: SolrHelperService
      Determines if there is a locale prefix that needs to be applied to the given field for this particular request. By default, a locale prefix is not applicable for category, explicitCategory, or fields that have type Price. Also, it is not applicable for non-translatable fields
      • Note: This method should NOT return null. There must be a default locale configured.
      Specified by:
      getLocalePrefix in interface SolrHelperService
      Returns:
      the global prefix if there is one, "" if there isn't
    • getDefaultLocalePrefix

      public String getDefaultLocalePrefix()
      Specified by:
      getDefaultLocalePrefix in interface SolrHelperService
      Returns:
      the default locale's prefix
    • getDefaultLocale

      public Locale getDefaultLocale()
      Description copied from interface: SolrHelperService
      Returns the default locale. Will cache the result for subsequent use.

      Note: There is no currently configured cache invalidation strategy for the the default locale. Override this method to provide for one if you need it.

      Specified by:
      getDefaultLocale in interface SolrHelperService
      Returns:
      the default locale
    • getPropertyValue

      public Object getPropertyValue(Object object, Field field) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
      Description copied from interface: SolrHelperService
      See getPropertyValue(Object, String)
      Specified by:
      getPropertyValue in interface SolrHelperService
      Returns:
      Throws:
      NoSuchMethodException
      InvocationTargetException
      IllegalAccessException
    • getPropertyValue

      public Object getPropertyValue(Object object, String propertyName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
      Description copied from interface: SolrHelperService

      This method is meant to behave in a similar way to Apache's PropertyUtils.getProperty(Object, String). This is attempting to get the value or values for a property using the property name specified in field.getPropertyName(). The real difference with this method is that it iterates over Collections, Map values, and arrays until it reaches end of the property name. For example, consider a Product and the property name "defaultSku.fees.currency.currencyCode".

      The property "fees" is a collection of SkuFee objects on the Sku. If an Product is passed to this method, with a field defining a property name of "defaultSku.fees.currency.currencyCode", this method will return a Collection of Strings. Specifically, it will return a Set of Strings.

      The point is, for Solr indexing, it is often desirable to specify all of the values associated with a product for a given Solr field. In this case, you are trying to get all of the unique currency codes associated with the collection of fees associated with the default Sku for the given product.

      This works similarly for Maps, Collections, Dates, Strings, Integers, Longs, and other primitives. Note, though, that this will return complex objects as well, if you do not specify the more primitive property that you are trying to access. For example, if you used "defaultSku.fees.currency" as a property name, you would get a collection of BroadleafCurrency objects back. Solr will not be happy if you try to index these.

      Note that, for arrays, this method only works with one dimensional arrays.

      For Maps, if a key is not specified, this method ignores the key, and iterates over the values collection and treats the values the same way that it treats any other collection. If they key is specified, then this method returns the keyed value rather than all of the values.

      So, for example, if you have a product and a property such as "productAttributes(heatRange).value", it will return a single value if there is a ProductAttribute keyed by "heatRange", or null if there is not. If you use the property "productAttributes.value" then is will return a collection of the values associated with each of the values in the productAttributes map.

      In this regard it is quite different than PropertyUtils.getMappedProperty(Object, String).

      Keep in mind that, since this method returns either a Collection or a single object that is not a Map or Array, you need to make sure that the field can handle such a value. For example, if your field is intended to index a collection of Strings, you need to make sure Solr's definition of this field (or dynamic field) is a multi-valued type according to your Solr schema definition (e.g. _txt or _ss or _is, etc.).

      Specified by:
      getPropertyValue in interface SolrHelperService
      Returns:
      Throws:
      NoSuchMethodException
      InvocationTargetException
      IllegalAccessException
    • optimizeIndex

      public void optimizeIndex(org.apache.solr.client.solrj.SolrClient server) throws ServiceException, IOException
      Description copied from interface: SolrHelperService
      Tells Solr to optimize the index. This is an expensive operation and should be used rarely or never.
      Specified by:
      optimizeIndex in interface SolrHelperService
      Parameters:
      server - The server to use to do the operation
      Throws:
      ServiceException
      IOException
    • optimizeIndex

      public void optimizeIndex(String collection, org.apache.solr.client.solrj.SolrClient server) throws ServiceException, IOException
      Description copied from interface: SolrHelperService
      Tells Solr to optimize the index. This is an expensive operation and should be used rarely or never.
      Specified by:
      optimizeIndex in interface SolrHelperService
      Parameters:
      collection - The collection to operate on
      server - The server to use to do the operation
      Throws:
      ServiceException
      IOException
    • scrubFacetValue

      public String scrubFacetValue(String facetValue)
      Specified by:
      scrubFacetValue in interface SolrHelperService
      Returns:
    • sanitizeQuery

      public String sanitizeQuery(String query)
      Description copied from interface: SolrHelperService
      Strips out or replaces certain characters / substrings.
      Specified by:
      sanitizeQuery in interface SolrHelperService
      Returns:
    • buildSearchFacetDTOs

      public List<SearchFacetDTO> buildSearchFacetDTOs(List<SearchFacet> searchFacets)
      Description copied from interface: SolrHelperService
      Builds a list of SearchFacetDTOs from a list of SearchFacets.
      Specified by:
      buildSearchFacetDTOs in interface SolrHelperService
      Returns:
    • isFacetAvailable

      public boolean isFacetAvailable(SearchFacet facet, Map<String,String[]> params)
      Description copied from interface: SolrHelperService
      Checks to see if the requiredFacets condition for a given facet is met.
      Specified by:
      isFacetAvailable in interface SolrHelperService
      Returns:
    • getSolrRangeString

      public String getSolrRangeString(String fieldName, BigDecimal minValue, BigDecimal maxValue)
      Description copied from interface: SolrHelperService
      Creates a range filter (e.g. field:[minValue TO maxValue])

      If minValue == null or maxValue == null, they are replaced by an '*' for wildcard functionality.

      Specified by:
      getSolrRangeString in interface SolrHelperService
      Returns:
    • getSolrRangeFunctionString

      public String getSolrRangeFunctionString(BigDecimal minValue, BigDecimal maxValue)
      Description copied from interface: SolrHelperService
      Returns a string representing a call to the frange solr function. it is not inclusive of lower limit, inclusive of upper limit.
      Specified by:
      getSolrRangeFunctionString in interface SolrHelperService
      Returns:
    • getSolrFieldTag

      public String getSolrFieldTag(String fieldName, String param, SearchFacetRange range)
      Description copied from interface: SolrHelperService
      Builds the value for a Solr param based on the given fieldName and range with the given local param name.

      If range == null, then this will produce a value for a facet.field param: {!param=fieldName}. Else, then this will produce a value for a facet.query param: {!ex=fieldName param=fieldName[range#minValue:range#maxValue] frange incl=false l=range#minValue u=range#maxValue}.

      Specified by:
      getSolrFieldTag in interface SolrHelperService
      Parameters:
      fieldName - Name of the index field
      param - Name of the local param (e.g., key, ex, tag)
      range - SearchFacetRange representing the range for which to create a facet.query.
      Returns:
      the value for a Solr param based on the given tagField and range with the given local param name.
    • buildSolrFacetField

      protected String buildSolrFacetField(String fieldName, String param)
      Builds a facet.field Solr param based on the fieldName provided.
      Parameters:
      fieldName - Name of the index field (e.g., mgf_s, heatRange_i, price_p)
      param - Optional name of the param (e.g., tag, key, ex). Defaults to "ex".
      Returns:
      a facet.field Solr param based on the fieldName provided.
    • buildSolrFacetQuery

      protected String buildSolrFacetQuery(String fieldName, SearchFacetRange range, Boolean addExParam, String param)
      Builds a facet.query Solr param based on the range and fieldName provided.

      For example, if given the range of $0.00 - $5.00 on the price_p field, the default result would be {!ex=price_p key=price_p[0.00:5.00] frange incl=false l=0.00 u=5.00}.

      If addExParam == false, then this will produce {!key=price_p[0.00:5.00] frange incl=false l=0.00 u=5.00}.

      Parameters:
      fieldName - Name of the index field on which to query
      range - SearchFacetRange representing the range for which to create a facet.query.
      addExParam - Whether to add an exclude filter by tag ("ex") parameter to the query. This assumes that the filter has a tag matching the fieldName. Defaults to true.
      param - Optional name of the main param (e.g., tag, key, ex). Defaults to "key".
      Returns:
      a facet.query Solr param based on the range and fieldName provided.
    • setFacetResults

      public void setFacetResults(Map<String,SearchFacetDTO> namedFacetMap, org.apache.solr.client.solrj.response.QueryResponse response)
      Description copied from interface: SolrHelperService
      Builds out the DTOs for facet results from the search. This will then be used by the view layer to display which values are available given the current constraints as well as the count of the values.
      Specified by:
      setFacetResults in interface SolrHelperService
    • sortFacetResults

      public void sortFacetResults(Map<String,SearchFacetDTO> namedFacetMap)
      Description copied from interface: SolrHelperService
      Invoked to sort the facet results. This method will use the natural sorting of the value attribute of the facet (or, if value is null, the minValue of the facet result). Override this method to customize facet sorting for your given needs.
      Specified by:
      sortFacetResults in interface SolrHelperService
    • attachFacets

      @Deprecated public void attachFacets(org.apache.solr.client.solrj.SolrQuery query, Map<String,SearchFacetDTO> namedFacetMap)
      Deprecated.
      Description copied from interface: SolrHelperService
      Notifies solr about which facets you want it to determine results and counts for.
      Specified by:
      attachFacets in interface SolrHelperService
    • attachFacets

      public void attachFacets(org.apache.solr.client.solrj.SolrQuery query, Map<String,SearchFacetDTO> namedFacetMap, SearchCriteria searchCriteria)
      Description copied from interface: SolrHelperService
      Notifies solr about which facets you want it to determine results and counts for.
      Specified by:
      attachFacets in interface SolrHelperService
    • getSolrTaggedFieldString

      public String getSolrTaggedFieldString(String indexField, String tag, SearchFacetRange range)
      Description copied from interface: SolrHelperService
      Returns a fully composed solr field string. Given indexField = a, tag = ex, and a non-null range, would produce the following String: {!tag=a frange incl=false l=minVal u=maxVal}a
      Specified by:
      getSolrTaggedFieldString in interface SolrHelperService
      Returns:
    • getResponseDocuments

      public List<org.apache.solr.common.SolrDocument> getResponseDocuments(org.apache.solr.client.solrj.response.QueryResponse response)
      Description copied from interface: SolrHelperService
      Determines the list of SolrDocuments from the QueryResponse
      Specified by:
      getResponseDocuments in interface SolrHelperService
      Returns:
    • getSortableFieldTypes

      protected List<String> getSortableFieldTypes()
    • attachSortClause

      public void attachSortClause(org.apache.solr.client.solrj.SolrQuery query, SearchCriteria searchCriteria, String defaultSort)
      Description copied from interface: SolrHelperService
      Sets up the sorting criteria. This will support sorting by multiple fields at a time
      Specified by:
      attachSortClause in interface SolrHelperService
    • getSortOrder

      protected org.apache.solr.client.solrj.SolrQuery.ORDER getSortOrder(String[] sortFieldsSegments, String sortQuery)
    • getSolrFieldKeyMap

      public Map<String,String> getSolrFieldKeyMap(SearchCriteria searchCriteria, List<IndexField> fields)
      Specified by:
      getSolrFieldKeyMap in interface SolrHelperService
    • getNamedFacetMap

      public Map<String,SearchFacetDTO> getNamedFacetMap(List<SearchFacetDTO> facets, SearchCriteria searchCriteria)
      Description copied from interface: SolrHelperService
      Returns a map of fully qualified solr index field key to the searchFacetDTO object
      Specified by:
      getNamedFacetMap in interface SolrHelperService
      Returns:
    • attachActiveFacetFilters

      public void attachActiveFacetFilters(org.apache.solr.client.solrj.SolrQuery query, Map<String,SearchFacetDTO> namedFacetMap, SearchCriteria searchCriteria)
      Description copied from interface: SolrHelperService
      Restricts the query by adding active facet filters.
      Specified by:
      attachActiveFacetFilters in interface SolrHelperService
    • getPropertyValueInternal

      protected Object getPropertyValueInternal(Object object, String[] components, int currentPosition) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
      Throws:
      NoSuchMethodException
      InvocationTargetException
      IllegalAccessException
    • copyPropertyToCollection

      protected void copyPropertyToCollection(Collection<Object> collection, Object o)
    • getSearchableIndexFields

      public List<IndexField> getSearchableIndexFields()
      Specified by:
      getSearchableIndexFields in interface SolrHelperService
    • getCategoryFilterIds

      public List<Long> getCategoryFilterIds(Category category, SearchCriteria searchCriteria)
      Specified by:
      getCategoryFilterIds in interface SolrHelperService