Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable location search with Sphinx #3256

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/helpers/feature_flag_helper.rb
Expand Up @@ -68,6 +68,6 @@ def search_engine
end

def location_search_available
search_engine == :zappy
true
end
end
2 changes: 2 additions & 0 deletions app/indices/listing_index.rb
Expand Up @@ -26,6 +26,8 @@
has community_id
has custom_dropdown_field_values.selected_options.id, :as => :custom_dropdown_field_options, :type => :integer, :multi => true
has custom_checkbox_field_values.selected_options.id, :as => :custom_checkbox_field_options, :type => :integer, :multi => true
has 'RADIANS(locations.latitude)', as: :latitude, type: :float
has 'RADIANS(locations.longitude)', as: :longitude, type: :float

set_property :enable_star => true

Expand Down
Expand Up @@ -2,9 +2,12 @@ module ListingIndexService::Search::DatabaseSearchHelper

module_function

def success_result(count, listings, includes)
Result::Success.new(
{count: count, listings: listings.map { |l| ListingIndexService::Search::Converters.listing_hash(l, includes) }})
def success_result(count, listings, includes, distances = {})
converted_listings = listings.map do |listing|
distance_hash = distances[listing.id] || {}
ListingIndexService::Search::Converters.listing_hash(listing, includes, distance_hash)
end
Result::Success.new({count: count, listings: converted_listings})
end

def fetch_from_db(community_id:, search:, included_models:, includes:)
Expand Down
39 changes: 37 additions & 2 deletions app/services/listing_index_service/search/sphinx_adapter.rb
Expand Up @@ -61,13 +61,16 @@ def search_with_sphinx(community_id:, search:, included_models:, includes:)
DatabaseSearchHelper.success_result(0, [], nil)
else

geo_search = parse_geo_search_params(search)

with = HashUtils.compact(
{
community_id: community_id,
category_id: search[:categories], # array of accepted ids
listing_shape_id: search[:listing_shape_id],
price_cents: search[:price_cents],
listing_id: numeric_search_match_listing_ids,
geodist: geo_search[:distance_max]
})

selection_groups = search[:fields].select { |v| v[:type] == :selection_group }
Expand All @@ -88,12 +91,14 @@ def search_with_sphinx(community_id:, search:, included_models:, includes:)
star: true,
with: with,
with_all: with_all,
order: 'sort_date DESC',
order: geo_search[:order] || 'sort_date DESC',
geo: geo_search[:origin],
max_query_time: 1000 # Timeout and fail after 1s
)

begin
DatabaseSearchHelper.success_result(models.total_entries, models, includes)
distances_hash = geo_search[:origin] ? collect_geo_distances(models, search[:distance_unit]) : {}
DatabaseSearchHelper.success_result(models.total_entries, models, includes, distances_hash)
rescue ThinkingSphinx::SphinxError => e
Result::Error.new(e)
end
Expand All @@ -113,5 +118,35 @@ def selection_groups(groups)
groups[:values]
end
end

DISTANCE_UNIT_FACTORS = { miles: 1609.0, km: 1000.0 }

def parse_geo_search_params(search)
return {} unless search[:latitude].present? && search[:longitude].present?

geo_params = {
order: (search[:sort] == :distance ? 'geodist ASC' : nil),
origin: [radians(search[:latitude]), radians(search[:longitude])]
}

if search[:distance_max].present?
max_distance_meters = search[:distance_max] * DISTANCE_UNIT_FACTORS[search[:distance_unit]]
geo_params[:distance_max] = 0..max_distance_meters
end

geo_params
end

def radians(degrees)
degrees * Math::PI / 180
end

def collect_geo_distances(models, geo_unit)
models.each_with_object({}) do |listing, result|
# get distance from ThinkingSphinx::Search::Glaze / DistancePane
distance = listing.distance / DISTANCE_UNIT_FACTORS[geo_unit]
result[listing.id] = { distance_unit: geo_unit, distance: distance }
end
end
end
end