11class SubscriptionVacanciesMatchingQuery
22 attr_reader :scope
33
4- # British National Grid SRID (EPSG:27700) is a projected coordinate system used for mapping in Great Britain.
5- # It provides coordinates in meters, which is useful for distance calculations, which we need
6- # for radius-based searches.
7- # It is significantly more accurate for distance calculations in Great Britain that EPSG:3857 (Web Mercator).
8- # EPSG:3857 distort distances and areas, especially as you move away from the equator. What would cause a multiplier
9- # between 1.5x and 1.7x for radius/buffer distances in our case to get the matches we would expect.
10- BRITISH_NATIONAL_GRID_SRID = 27700 # rubocop:disable Style/NumericLiterals
11-
124 # Builds the query to find the IDs for the vacancies matching the subscription criteria.
135 # The subquery is needed to be able to combine our requirements into a valid single SQL statement:
146 # - retrieve unique DISTINCT ON vacancy ids: As the location filter may return the same vacancy multiple times (vacancy for multiple orgs).
@@ -177,9 +169,9 @@ def location_filter(scope, subscription_location, subscription)
177169 # 'area_before_type_cast' and 'geopoint_before_type_cast' are used to avoid casting the fields into RGeo objects.
178170 # This reduces memory usage and speeds up the query. As we don't need to use the actual objects in Ruby code,
179171 # just need to know if they are present in DB.
180- if subscription . area_before_type_cast . present?
172+ if subscription . uk_area_before_type_cast . present?
181173 location_by_area_filter ( scope , subscription )
182- elsif subscription . geopoint_before_type_cast . present? && subscription . radius_in_metres . present?
174+ elsif subscription . uk_geopoint_before_type_cast . present? && subscription . radius_in_metres . present?
183175 location_by_geopoint_filter ( scope , subscription )
184176 else
185177 scope . none # Invalid location filter (having no area or geopoint) returns no matches
@@ -197,9 +189,11 @@ def location_filter(scope, subscription_location, subscription)
197189 # Including 'publish_on' in the distinct: The provided scope may be ordered by publish on date. When using distinct
198190 # with ordering, Postgres requires all selected columns to be included in the distinct clause or will fail during execution.
199191 def location_by_area_filter ( scope , subscription )
192+ subscriptions = Subscription . arel_table
193+ organisations = Organisation . arel_table
200194 scope . joins ( "INNER JOIN subscriptions ON subscriptions.id = '#{ subscription . id } '" )
201195 . joins ( :organisations )
202- . where ( "ST_Contains( subscriptions.area, organisations.geopoint::geometry)" )
196+ . where ( subscriptions [ :uk_area ] . st_contains ( organisations [ :uk_geopoint ] ) )
203197 end
204198
205199 # Filter vacancies where their organisations' geopoints fall within the subscription's radius from the subscription's
@@ -214,8 +208,8 @@ def location_by_area_filter(scope, subscription)
214208 def location_by_geopoint_filter ( scope , subscription )
215209 scope . joins ( "INNER JOIN subscriptions ON subscriptions.id = '#{ subscription . id } '" )
216210 . joins ( :organisations )
217- . where ( "ST_DWithin(ST_Transform( organisations.geopoint ::geometry, #{ BRITISH_NATIONAL_GRID_SRID } ) ,
218- ST_Transform( subscriptions.geopoint, #{ BRITISH_NATIONAL_GRID_SRID } ) ,
211+ . where ( "ST_DWithin(organisations.uk_geopoint ::geometry,
212+ subscriptions.uk_geopoint ,
219213 subscriptions.radius_in_metres)" )
220214 end
221215end
0 commit comments