class SolidusRecommendations::Recommendable::Products

Provides methods to get recommended products based on certain criteria such as “Bought Together” or “Users also bought”

Constants

ACCEPTED_INDICES

Acceptable indices to pass as index option to methods

Public Instance Methods

get(product, options = {}) click to toggle source

Gets recommended products

@example Get recommended products based on user index.

product = Spree::Product.find(4)
recommended = SolidusRecommendations::Client.new
recommended.products.get(product)

# Good for getting recommendations based on what other users have
# have purchased.

@example Get recommended products based on order index.

product = Spree::Product.find(4)
recommmended = SolidusRecommendations::Client.new
recommended.products.get(product, index: :order)

# Good for getting recommendations based on what others checkout with
# frequently.

@param [Spree::Product, Integer] product The product to base recommendations off of. @param [Hash] options @option options [Symbol, String] :index The index to perform aggregation on. (*Defaults to :user*) @option options [Integer] :size The number of recommendations to return. (*Defaults to 10*)

@return [Array<Spree::Product]

# File lib/solidus_recommendations/recommendable/products.rb, line 41
def get(product, options = {})
  return [] if product.nil?

  options.deep_symbolize_keys!
  index = options.delete(:index) || :user
  size = options.delete(:size) || 10

  # If index is not supported then we will get a weird undefined
  # method error. This error will make more sense.
  raise Errors::NonSupportedIndex unless ACCEPTED_INDICES.include?(index.to_sym)

  product = convert_to_id([product]).first
  aggs = send("#{index}_index_significant_terms", product, size)

  from_significant_terms(aggs, [product], Spree::Product)
end

Private Instance Methods

order_index_significant_terms(product, size = 10) click to toggle source
# File lib/solidus_recommendations/recommendable/products.rb, line 60
def order_index_significant_terms(product, size = 10)
  payload = significant_terms_query('product_ids', product, size)
  response = Spree::Order.__elasticsearch__.search(payload)

  response.aggregations.recommended
end
significant_terms_query(field, value, size) click to toggle source

Builds body for significant terms aggregation.

# File lib/solidus_recommendations/recommendable/products.rb, line 77
def significant_terms_query(field, value, size)
  {
    size: 0,
    query: {
      bool: {
        filter: [
          { term: { "#{field}": value } }
        ]
      }
    },
    aggregations: {
      recommended: {
        significant_terms: {
          field: field,
          size: size + 1
        }
      }
    }
  }
end
user_index_significant_terms(product, size = 10) click to toggle source
# File lib/solidus_recommendations/recommendable/products.rb, line 67
def user_index_significant_terms(product, size = 10)
  payload = significant_terms_query('purchased_product_ids', product, size)
  response = Spree.user_class.__elasticsearch__.search(payload)

  response.aggregations.recommended
end