From d769861e69142b585b4e4b0d6855114519f8c43a Mon Sep 17 00:00:00 2001 From: Eugene Burmakin Date: Mon, 3 Mar 2025 21:34:06 +0100 Subject: [PATCH] Use postgis to find existing places --- app/jobs/overland/batch_creating_job.rb | 3 +-- app/jobs/owntracks/point_creating_job.rb | 3 +-- app/serializers/api/place_serializer.rb | 4 ++-- app/serializers/api/visit_serializer.rb | 4 ++-- app/services/points/params.rb | 3 +-- .../reverse_geocoding/places/fetch_data.rb | 7 ++++--- app/services/visits/prepare.rb | 3 +-- app/services/visits/smart_detect.rb | 20 +++++++++++++++---- 8 files changed, 28 insertions(+), 19 deletions(-) diff --git a/app/jobs/overland/batch_creating_job.rb b/app/jobs/overland/batch_creating_job.rb index 6c6ca3ea..944a72e2 100644 --- a/app/jobs/overland/batch_creating_job.rb +++ b/app/jobs/overland/batch_creating_job.rb @@ -17,8 +17,7 @@ class Overland::BatchCreatingJob < ApplicationJob def point_exists?(params, user_id) Point.exists?( - latitude: params[:latitude], - longitude: params[:longitude], + lonlat: "POINT(#{params[:longitude]} #{params[:latitude]})", timestamp: params[:timestamp], user_id: ) diff --git a/app/jobs/owntracks/point_creating_job.rb b/app/jobs/owntracks/point_creating_job.rb index 56425396..86f6670d 100644 --- a/app/jobs/owntracks/point_creating_job.rb +++ b/app/jobs/owntracks/point_creating_job.rb @@ -13,8 +13,7 @@ class Owntracks::PointCreatingJob < ApplicationJob def point_exists?(params, user_id) Point.exists?( - latitude: params[:latitude], - longitude: params[:longitude], + lonlat: "POINT(#{params[:longitude]} #{params[:latitude]})", timestamp: params[:timestamp], user_id: ) diff --git a/app/serializers/api/place_serializer.rb b/app/serializers/api/place_serializer.rb index 3df93efc..2857379a 100644 --- a/app/serializers/api/place_serializer.rb +++ b/app/serializers/api/place_serializer.rb @@ -9,8 +9,8 @@ class Api::PlaceSerializer { id: place.id, name: place.name, - longitude: place.longitude, - latitude: place.latitude, + longitude: place.lon, + latitude: place.lat, city: place.city, country: place.country, source: place.source, diff --git a/app/serializers/api/visit_serializer.rb b/app/serializers/api/visit_serializer.rb index e2eb4a9a..31ff7cdf 100644 --- a/app/serializers/api/visit_serializer.rb +++ b/app/serializers/api/visit_serializer.rb @@ -16,8 +16,8 @@ class Api::VisitSerializer name: name, status: status, place: { - latitude: visit.place&.latitude || visit.area&.latitude, - longitude: visit.place&.longitude || visit.area&.longitude, + latitude: visit.place&.lat || visit.area&.latitude, + longitude: visit.place&.lon || visit.area&.longitude, id: visit.place&.id } } diff --git a/app/services/points/params.rb b/app/services/points/params.rb index 8c1b8a51..fc2348dc 100644 --- a/app/services/points/params.rb +++ b/app/services/points/params.rb @@ -14,8 +14,7 @@ class Points::Params next unless params_valid?(point) { - latitude: point[:geometry][:coordinates][1], - longitude: point[:geometry][:coordinates][0], + lonlat: "POINT(#{point[:geometry][:coordinates][0]} #{point[:geometry][:coordinates][1]})", battery_status: point[:properties][:battery_state], battery: battery_level(point[:properties][:battery_level]), timestamp: DateTime.parse(point[:properties][:timestamp]), diff --git a/app/services/reverse_geocoding/places/fetch_data.rb b/app/services/reverse_geocoding/places/fetch_data.rb index d6b5c059..5ed94afd 100644 --- a/app/services/reverse_geocoding/places/fetch_data.rb +++ b/app/services/reverse_geocoding/places/fetch_data.rb @@ -32,8 +32,7 @@ class ReverseGeocoding::Places::FetchData place.update!( name: place_name(data), - latitude: data['geometry']['coordinates'][1], - longitude: data['geometry']['coordinates'][0], + lonlat: "POINT(#{data['geometry']['coordinates'][0]} #{data['geometry']['coordinates'][1]})", city: data['properties']['city'], country: data['properties']['country'], geodata: data, @@ -79,7 +78,9 @@ class ReverseGeocoding::Places::FetchData return found_place if found_place.present? Place.find_or_initialize_by( - lonlat: "POINT(#{place_data['geometry']['coordinates'][0].to_f.round(5)} #{place_data['geometry']['coordinates'][1].to_f.round(5)})" + lonlat: "POINT(#{place_data['geometry']['coordinates'][0].to_f.round(5)} #{place_data['geometry']['coordinates'][1].to_f.round(5)})", + latitude: place_data['geometry']['coordinates'][1].to_f.round(5), + longitude: place_data['geometry']['coordinates'][0].to_f.round(5) ) end diff --git a/app/services/visits/prepare.rb b/app/services/visits/prepare.rb index fb60d90f..4e4c56ce 100644 --- a/app/services/visits/prepare.rb +++ b/app/services/visits/prepare.rb @@ -67,8 +67,7 @@ class Visits::Prepare center_point = group.first { - latitude: center_point.lat, - longitude: center_point.lon, + lonlat: "POINT(#{center_point.lon} #{center_point.lat})", radius: calculate_radius(center_point, group), points: group, duration: (group.last.timestamp - group.first.timestamp).to_i / 60, diff --git a/app/services/visits/smart_detect.rb b/app/services/visits/smart_detect.rb index 8ae6759c..b0075ed5 100644 --- a/app/services/visits/smart_detect.rb +++ b/app/services/visits/smart_detect.rb @@ -297,7 +297,7 @@ class Visits::SmartDetect status: :suggested ) - visit_data[:points].each { |point| point.update!(visit_id: visit.id) } + Point.where(id: visit_data[:points].map(&:id)).update_all(visit_id: visit.id) visit end @@ -311,16 +311,28 @@ class Visits::SmartDetect end def find_or_create_place(visit_data) - # Round coordinates to reduce duplicate places lat = visit_data[:center_lat].round(5) lon = visit_data[:center_lon].round(5) + name = visit_data[:suggested_name] + # Define the search radius in meters + search_radius = 100 # Adjust this value as needed + + # Use the Nearable module to find existing places within the search radius + existing_place = Place.near([lat, lon], search_radius, :m).where(name: name).first + + return existing_place if existing_place + + # If no existing place is found, create a new one place = Place.find_or_initialize_by( - latitude: lat, - longitude: lon + lonlat: "POINT(#{lon} #{lat})" ) unless place.persisted? + # Set latitude and longitude if needed + place.latitude = lat + place.longitude = lon + # Get reverse geocoding data geocoded_data = Geocoder.search([lat, lon])