Skip to content

Commit

Permalink
Indexing product with Opensearch
Browse files Browse the repository at this point in the history
  • Loading branch information
channainfo committed Jul 11, 2024
1 parent 997ee72 commit cb3543b
Show file tree
Hide file tree
Showing 15 changed files with 890 additions and 21 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SEARCH_SERVER_URL="http://localhost:9200"
31 changes: 17 additions & 14 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,20 @@ PATH
aws-sdk-s3
byebug
dry-validation (~> 1.10)
elasticsearch (~> 8.5)
exception_notification
font-awesome-sass (~> 6.4.0)
google-cloud-recaptcha_enterprise
googleauth
interactor (~> 3.1)
jwt (>= 2.5.0)
noticed (~> 1.6)
oj
opensearch-ruby
phonelib
premailer-rails
rails (~> 7.0.4)
rqrcode (~> 2.0)
searchkick (~> 5.1)
searchkick (~> 5.3.1)
simple_calendar (~> 2.4)
spree (>= 4.5.0)
spree_api_v1 (>= 4.5.0)
Expand Down Expand Up @@ -147,6 +148,9 @@ GEM
activerecord (>= 4.2)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0)
appraisal (2.5.0)
bundler
rake
Expand Down Expand Up @@ -201,6 +205,7 @@ GEM
execjs (~> 2.0)
base64 (0.1.1)
bcrypt (3.1.19)
bigdecimal (3.1.8)
bootstrap (4.6.2)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 1.16.1, < 2)
Expand All @@ -226,7 +231,7 @@ GEM
activesupport (>= 3.0.0)
chunky_png (1.4.0)
coderay (1.1.3)
concurrent-ruby (1.2.2)
concurrent-ruby (1.3.3)
connection_pool (2.4.1)
console (1.23.2)
fiber-annotation
Expand Down Expand Up @@ -297,14 +302,6 @@ GEM
zeitwerk (~> 2.6)
ecma-re-validator (0.4.0)
regexp_parser (~> 2.2)
elastic-transport (8.3.0)
faraday (< 3)
multi_json
elasticsearch (8.10.0)
elastic-transport (~> 8)
elasticsearch-api (= 8.10.0)
elasticsearch-api (8.10.0)
multi_json
erubi (1.12.0)
exception_notification (4.5.0)
actionmailer (>= 5.2, < 8)
Expand Down Expand Up @@ -430,7 +427,7 @@ GEM
domain_name (~> 0.5)
http-form_data (2.3.0)
httpclient (2.8.3)
i18n (1.14.1)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
Expand Down Expand Up @@ -494,7 +491,7 @@ GEM
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.4)
minitest (5.20.0)
minitest (5.24.1)
monetize (1.12.0)
money (~> 6.12)
money (6.16.0)
Expand Down Expand Up @@ -524,6 +521,11 @@ GEM
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
oj (3.16.4)
bigdecimal (>= 3.0)
opensearch-ruby (3.3.0)
faraday (>= 1.0, < 3)
multi_json (>= 1.0)
orm_adapter (0.5.0)
os (1.1.4)
parallel (1.23.0)
Expand Down Expand Up @@ -680,7 +682,7 @@ GEM
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
searchkick (5.3.0)
searchkick (5.3.1)
activemodel (>= 6.1)
hashie
select2-rails (4.0.13)
Expand Down Expand Up @@ -862,6 +864,7 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
annotate
brakeman
net-smtp
pg
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module SpreeCmCommissioner
module CustomProductSerializable
def product_master_images(product, ignore_detailed_images=false)
product.master.images.map do |image|
data = {
id: image.id,
viewable_type: image.viewable_type,
viewable_id: image.viewable_id,
styles: [ image.image_style(:product) ],
}

# Improve unnecesary loading v1.2.0 and maintain backward compatibility
data[:mobile_image_styles] = image.mobile_image_styles if ignore_detailed_images == false
data
end
end

def product_vendor(product)
return {} if product.vendor.nil?

{
id: product.vendor.id,
is_type_vmall: product.vendor.type_vmall?,
vendor_type: product.vendor.vendor_type,
slug: product.vendor.slug,
name: product.vendor.name,
}
end
end
end
130 changes: 130 additions & 0 deletions app/models/concerns/spree_cm_commissioner/product_indexable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
module SpreeCmCommissioner
module ProductIndexable
extend ActiveSupport::Concern

included do
searchkick word_middle: %i[name vendor_name],
searchable: %i[name vendor_name description],
text_middle: %i[description],
suggest: %i[name vendor_name]
end

def review_rating
0
end

def vendor_rating
0
end

def impressions_count
0
end

def conversions_count
0
end

def whishedlists_count
0
end

# [ variants_including_master: {option_values: { option_type: :translations } }]
def filterable_option_types_for_es_index
json = {}

# [{ size: 'M', color: 'Red', conditon: 'Good'}, { size: 'L', color: 'Red', conditon: 'Good'}]
variants_including_master.each do |v|
v.option_values.each do |option_value|
option_type = option_value.option_type
next if !option_type.filterable?

index_key = option_type.filter_name
json[index_key] ||= []
json[index_key] << option_value.id
end
end

json
end

# product_properties: [:translations, :property]
# product_properties: [:translations, property: :translations ]
def filterable_properties_for_es
json = {}

product_properties.includes(:property ).each do |pp|
# data is empty somehow.
next if !pp.property_id.present?
next if !pp.property.filterable?

json[pp.property.filter_name] = pp.id
end

json
end

def vendor_for_es_index
{
vendor_id: vendor&.id,
vendor_slug: vendor&.slug,
vendor_name: vendor&.name
}
end

def index_data
{}
end

def search_data
# possible: Infinity
discount = compare_at_price.present? && compare_at_price.to_f > 0 ? (100 * (compare_at_price.to_f - price.to_f) / compare_at_price.to_f).to_i : 0

# possible: Infinity
on_hand = (total_on_hand.infinite? ? nil : total_on_hand)

all_variants = variants_including_master.pluck(:id, :sku)
skus = all_variants.map(&:last).reject(&:blank?)

es_fields = {
id: id,
name: name,
product_slug: slug,
description: description,
active: available?,
in_stock: in_stock?,
price: price.to_f,
compare_at_price: compare_at_price.to_f,
discount_amount: discount,
skus: skus,
total_on_hand: on_hand,
product_type: product_type,

# boost user purchase
purchaser_ids: purchasers.uniq.pluck(:id),

# meta data
created_at: created_at,
updated_at: updated_at,

# analytics
impressions_count: impressions_count,
conversions_count: conversions_count,
whishedlists_count: whishedlists_count,
review_rating: review_rating,
vendor_rating: vendor_rating,

# TODO: category, brand, industry
taxon_ids: taxon_and_ancestors.map(&:id),
taxon_names: taxon_and_ancestors.map(&:name)
}

es_fields.merge!(filterable_option_types_for_es_index)
es_fields.merge!(filterable_properties_for_es)
es_fields.merge!(vendor_for_es_index)
es_fields.merge!(index_data)

es_fields
end
end
end
Loading

0 comments on commit cb3543b

Please sign in to comment.