Commit 04000e0cdb96e1868e185d4dfd9177a7f23db861

Authored by Andrew Kane
1 parent 089ebf63

Added section on performant conversions [skip ci]

Showing 1 changed file with 60 additions and 1 deletions   Show diff stats
README.md
... ... @@ -543,7 +543,7 @@ Reindex and set up a cron job to add new conversions daily.
543 543 rake searchkick:reindex CLASS=Product
544 544 ```
545 545  
546   -**Note:** For better performance, check out [this gist](https://gist.github.com/ankane/09af4746076112fc64f684fcb0d5b6da).
  546 +**Note:** For a more performant (but slightly more advanced) approach, check out [performant conversions](#performant-conversions).
547 547  
548 548 ### Personalized Results
549 549  
... ... @@ -1158,6 +1158,65 @@ Reindex and search with:
1158 1158 Business.search "ice cream", routing: params[:city_id]
1159 1159 ```
1160 1160  
  1161 +### Performant Conversions
  1162 +
  1163 +Split out conversions into a separate method so you can use partial reindexing, and cache conversions to prevent N+1 queries.
  1164 +
  1165 +```ruby
  1166 +class Product < ActiveRecord::Base
  1167 + def search_data
  1168 + {
  1169 + name: name
  1170 + }.merge(search_conversions)
  1171 + end
  1172 +
  1173 + def search_conversions
  1174 + {
  1175 + conversions: Rails.cache.read("search_conversions:#{self.class.name}:#{id}") || {}
  1176 + }
  1177 + end
  1178 +end
  1179 +```
  1180 +
  1181 +Create a service to update the cache and reindex records with new conversions.
  1182 +
  1183 +```ruby
  1184 +class ReindexConversions
  1185 + def self.perform(model)
  1186 + class_name = model.name
  1187 + recently_converted_ids =
  1188 + Searchjoy::Search.where("convertable_type = ? AND converted_at > ?", class_name, 1.days.ago)
  1189 + .pluck(:convertable_id).sort
  1190 +
  1191 + recently_converted_ids.in_groups_of(1000, false) do |ids|
  1192 + # fetch conversions and group by record
  1193 + conversions_by_record = {}
  1194 + conversions =
  1195 + Searchjoy::Search.where(convertable_id: ids, convertable_type: class_name)
  1196 + .group(:convertable_id, :query).uniq.count(:user_id)
  1197 +
  1198 + conversions.each do |(id, query), count|
  1199 + (conversions_by_record[id] ||= {})[query] = count
  1200 + end
  1201 +
  1202 + # write to cache
  1203 + conversions_by_record.each do |id, conversions|
  1204 + Rails.cache.write("search_conversions:#{class_name}:#{id}", conversions)
  1205 + end
  1206 +
  1207 + # partial reindex
  1208 + class_name.constantize.where(id: ids).reindex(:search_conversions)
  1209 + end
  1210 + end
  1211 +end
  1212 +```
  1213 +
  1214 +Use the service with:
  1215 +
  1216 +```ruby
  1217 +ReindexConversions.perform(Product)
  1218 +```
  1219 +
1161 1220 ## Large Data Sets
1162 1221  
1163 1222 ### Background Reindexing [experimental, ActiveRecord only]
... ...