geokit / geokit-rails

Official Geokit plugin for Rails/ActiveRecord. Provides location-based goodness for your Rails app. Requires the Geokit gem.
MIT License
1.57k stars 245 forks source link

Selecting a record from a result queries the database again #123

Open nesrual opened 7 years ago

nesrual commented 7 years ago

Using Rails 5.1.1 and Ruby 2.3.3

2.3.3 :001 > locations = Location.by_distance(:origin => [37.792,-122.393])

This queries the database as expected:

  Location Load (2.9ms)  SELECT  "locations".* FROM "locations" WHERE (locations.lat IS NOT NULL AND locations.lng IS NOT NULL) ORDER BY
  (ACOS(least(1,COS(0.6595948309136971)*COS(-2.1361608313934197)*COS(RADIANS(locations.lat))*COS(RADIANS(locations.lng))+
     COS(0.6595948309136971)*SIN(-2.1361608313934197)*COS(RADIANS(locations.lat))*SIN(RADIANS(locations.lng))+
      SIN(0.6595948309136971)*SIN(RADIANS(locations.lat))))*3963.1899999999996)
      ASC LIMIT $1  [["LIMIT", 11]]

And we have an ActiveRecord_Relation:

2.3.3 :002 > locations.class
 => Location::ActiveRecord_Relation

Getting any record from the relation will query the database again:

2.3.3 :003 > locations.first
  Location Load (3.2ms)  SELECT  "locations".* FROM "locations" WHERE (locations.lat IS NOT NULL AND locations.lng IS NOT NULL) ORDER BY
      (ACOS(least(1,COS(0.6595948309136971)*COS(-2.1361608313934197)*COS(RADIANS(locations.lat))*COS(RADIANS(locations.lng))+
      COS(0.6595948309136971)*SIN(-2.1361608313934197)*COS(RADIANS(locations.lat))*SIN(RADIANS(locations.lng))+
      SIN(0.6595948309136971)*SIN(RADIANS(locations.lat))))*3963.1899999999996)
      ASC LIMIT $1  [["LIMIT", 1]]

Fetching the record again will use a cached result:

2.3.3 :004 > locations.first
 => #<Location id: 970, name: "9c28dcea-ef4f-4315-a07a-fb4cf2a5b6f4", lat: 99.665289316595, lng: 47.686835276217, distance: nil, created_at: "2017-05-27 05:55:56", updated_at: "2017-05-27 05:55:56">

What I don't quite understand is why the database is queried again? The result of locations ordered by distance is already fetched once.