mongoid-geospatial 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +61 -30
  3. data/lib/mongoid/geospatial/config/point.rb +5 -2
  4. data/lib/mongoid/geospatial/config.rb +2 -0
  5. data/lib/mongoid/geospatial/ext/rgeo_spherical_point_impl.rb +2 -0
  6. data/lib/mongoid/geospatial/fields/box.rb +2 -0
  7. data/lib/mongoid/geospatial/fields/circle.rb +2 -2
  8. data/lib/mongoid/geospatial/fields/line_string.rb +2 -0
  9. data/lib/mongoid/geospatial/fields/point.rb +18 -15
  10. data/lib/mongoid/geospatial/fields/polygon.rb +2 -0
  11. data/lib/mongoid/geospatial/geometry_field.rb +4 -2
  12. data/lib/mongoid/geospatial/helpers/delegate.rb +2 -0
  13. data/lib/mongoid/geospatial/helpers/spatial.rb +2 -0
  14. data/lib/mongoid/geospatial/helpers/sphere.rb +2 -0
  15. data/lib/mongoid/geospatial/version.rb +3 -1
  16. data/lib/mongoid/geospatial/wrappers/georuby.rb +2 -0
  17. data/lib/mongoid/geospatial/wrappers/rgeo.rb +2 -0
  18. data/lib/mongoid/geospatial.rb +144 -12
  19. metadata +5 -75
  20. data/.coveralls.yml +0 -1
  21. data/.gitignore +0 -49
  22. data/.hound.yml +0 -2
  23. data/.rspec +0 -3
  24. data/.rubocop.yml +0 -8
  25. data/.travis.yml +0 -33
  26. data/CHANGELOG.md +0 -23
  27. data/CONTRIBUTING.md +0 -118
  28. data/Gemfile +0 -17
  29. data/Guardfile +0 -16
  30. data/RELEASING.md +0 -62
  31. data/Rakefile +0 -20
  32. data/mongoid-geospatial.gemspec +0 -18
  33. data/spec/bench +0 -64
  34. data/spec/models/address.rb +0 -69
  35. data/spec/models/alarm.rb +0 -12
  36. data/spec/models/bar.rb +0 -14
  37. data/spec/models/bus.rb +0 -12
  38. data/spec/models/event.rb +0 -18
  39. data/spec/models/farm.rb +0 -13
  40. data/spec/models/person.rb +0 -91
  41. data/spec/models/phone.rb +0 -8
  42. data/spec/models/place.rb +0 -13
  43. data/spec/models/river.rb +0 -22
  44. data/spec/mongoid/geospatial/config_spec.rb +0 -22
  45. data/spec/mongoid/geospatial/fields/box_spec.rb +0 -8
  46. data/spec/mongoid/geospatial/fields/circle_spec.rb +0 -8
  47. data/spec/mongoid/geospatial/fields/line_string_spec.rb +0 -78
  48. data/spec/mongoid/geospatial/fields/point_spec.rb +0 -296
  49. data/spec/mongoid/geospatial/fields/polygon_spec.rb +0 -87
  50. data/spec/mongoid/geospatial/geospatial_spec.rb +0 -222
  51. data/spec/mongoid/geospatial/helpers/core_spec.rb +0 -35
  52. data/spec/mongoid/geospatial/helpers/delegate_spec.rb +0 -67
  53. data/spec/mongoid/geospatial/helpers/spatial_spec.rb +0 -40
  54. data/spec/mongoid/geospatial/helpers/sphere_spec.rb +0 -31
  55. data/spec/mongoid/geospatial/wrappers/georuby_spec.rb +0 -63
  56. data/spec/mongoid/geospatial/wrappers/rgeo_spec.rb +0 -115
  57. data/spec/mongoid.yml +0 -298
  58. data/spec/spec_helper.rb +0 -42
  59. data/spec/support/authentication.rb +0 -28
  60. data/spec/support/mongod.conf +0 -3
  61. data/spec/support/mongoid.yml +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c175628dbf99da911bb81c3c25b2665b3547506f910366a53d43eaabea99e410
4
- data.tar.gz: 8e38f228cc16e9a17cbe44dd2be01bd06e989d5e91d968a9b50a1885cc12eb8e
3
+ metadata.gz: 88d807a8e7011846e353f18fc6812fb55e578f371464c202fa726976c7fec6e6
4
+ data.tar.gz: 32f5124231bfe558a9a591520c90dda408f76995faa2030e67c39bee1e9f7b23
5
5
  SHA512:
6
- metadata.gz: a09b65028e7d0b27a88383dac691372e6b456ad0d72b3ef0159e8e9e33d7f6da78cb250038c6d592bbb667d9a6f6f864ac1ae8278eaed41b69277d0290a47399
7
- data.tar.gz: 843567a6bbe62c5551cd962c70a927e2dd8e19968c741ea014e384cf942b99aa75fa382969fe139cc07c835249fb7d864421713cb5e324e0495615fc14b7d30e
6
+ metadata.gz: f8beb1650724d7b54d7a2a35d2376597144d9290360f2571da28681ef11d3e3e0792bf562f0c904f762b0abaf09d43b9f8c8f1747cb4d7753a5f187a6c6d04c5
7
+ data.tar.gz: b457c28c88ab87968e76eeb00afca6e376e37cf2432df230fc88260ab44b9984c9cd11708deba53eb19fa4a19d27175d63042c5b142762707fe3bd1019107652
data/README.md CHANGED
@@ -176,26 +176,6 @@ field :location, type: Point, delegate: true
176
176
 
177
177
  Now instead of `instance.location.x` you may call `instance.x`.
178
178
 
179
- ## Nearby
180
-
181
- You can add a `spatial_scope` on your models. So you can query:
182
-
183
- ```ruby
184
- Bar.nearby(my.location)
185
- ```
186
-
187
- instead of
188
-
189
- ```ruby
190
- Bar.near(location: my.location)
191
- ```
192
-
193
- Good when you're drunk. Just add to your model:
194
-
195
- ```ruby
196
- spatial_scope :<field>
197
- ```
198
-
199
179
  ## Geometry
200
180
 
201
181
  You can also store Circle, Box, Line (LineString) and Polygons.
@@ -219,30 +199,81 @@ polygon.radius_sphere(5) # [[1.0, 1.0], 0.00048..]
219
199
 
220
200
  ## Query
221
201
 
222
- Before you proceed, make sure you have read this:
223
-
224
- http://mongoid.github.io/old/en/origin/docs/selection.html#standard
225
-
226
- All MongoDB queries are handled by Mongoid/Origin.
227
-
228
- http://www.rubydoc.info/github/mongoid/origin/Origin/Selectable
229
-
230
202
  You can use Geometry instance directly on any query:
231
203
 
232
- - near
204
+ ### near
233
205
 
234
206
  ```ruby
235
207
  Bar.near(location: person.house)
236
208
  Bar.where(:location.near => person.house)
237
209
  ```
238
210
 
239
- - near_sphere
211
+ ### near_sphere
240
212
 
241
213
  ```ruby
242
214
  Bar.near_sphere(location: person.house)
243
215
  Bar.where(:location.near_sphere => person.house)
244
216
  ```
245
217
 
218
+ ### nearby
219
+
220
+ You can add a `spatial_scope` on your models. So you can query:
221
+
222
+ ```ruby
223
+ Bar.nearby(my.location)
224
+ ```
225
+
226
+ instead of
227
+
228
+ ```ruby
229
+ Bar.near(location: my.location)
230
+ ```
231
+
232
+ Good when you're drunk. Just add to your model:
233
+
234
+ ```ruby
235
+ spatial_scope :<field>
236
+ ```
237
+
238
+ ### geo_near
239
+
240
+ The `geo_near` class method provides a more powerful way to query for documents based on proximity,
241
+ using MongoDB's `$geoNear` aggregation pipeline stage. This method allows for more complex
242
+ options and returns the distance to each matched document.
243
+
244
+ ```ruby
245
+ # Find places near [10, 20], using spherical calculations, up to 5km away,
246
+ # and get the distance.
247
+ # The :distanceField option specifies the name of the field that will contain the distance.
248
+ # The :limit option is applied as a separate $limit stage in the aggregation.
249
+ Place.geo_near(:location, [10, 20],
250
+ spherical: true,
251
+ maxDistance: 5000, # 5 kilometers in meters for spherical queries
252
+ distanceField: 'dist.calculated', # Default is 'distance'
253
+ query: { category: 'restaurant' }, # Optional: filter documents before geoNear
254
+ limit: 10)
255
+
256
+ # Iterate over results
257
+ Place.geo_near(:location, [10, 20], spherical: true).each do |place|
258
+ # 'place.distance' will be available if distanceField was 'distance' (the default)
259
+ # or 'place.dist_calculated' if distanceField was 'dist.calculated'
260
+ puts "#{place.name} is #{place.distance || place.dist_calculated} meters away."
261
+ end
262
+ ```
263
+
264
+ Key features and options for `geo_near`:
265
+
266
+ - `:spherical` (Boolean): If `true`, calculates distances using spherical geometry. Defaults to `false`.
267
+ - `:distanceField` (String): Name of the output field for the calculated distance. Defaults to `'distance'`.
268
+ - `:maxDistance` (Numeric): Maximum distance from the center point. (Meters for spherical, units of coordinates for planar).
269
+ - `:minDistance` (Numeric): Minimum distance from the center point.
270
+ - `:query` (Hash): A query to filter documents _before_ the `$geoNear` stage.
271
+ - `:limit` (Integer): Maximum number of documents to return (applied as a separate `$limit` stage).
272
+ - `:distanceMultiplier` (Numeric): A factor to multiply all distances.
273
+ - `:includeLocs` (String): Name of an output field that will contain the exact location on the document used for the distance calculation. Useful for multi-location fields or complex GeoJSON geometries.
274
+
275
+ The `geo_near` method returns an array of instantiated Mongoid documents, with the `distanceField` and `includeLocs` field (if specified) available as dynamic attributes on each model instance.
276
+
246
277
  - within_polygon
247
278
 
248
279
  ```ruby
@@ -1,17 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  module Config
4
6
  module Point
5
7
  extend self
6
8
 
7
- attr_accessor :x
8
- attr_accessor :y
9
+ attr_accessor :x, :y
9
10
 
10
11
  def reset!
12
+ # Now self.x and self.y refer to the public module accessors
11
13
  self.x = Mongoid::Geospatial.lng_symbols
12
14
  self.y = Mongoid::Geospatial.lat_symbols
13
15
  end
14
16
 
17
+ # Initialize the configuration
15
18
  reset!
16
19
  end
17
20
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  module Config
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RGeo
2
4
  module Geographic
3
5
  # RGeo Point
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  class Box < GeometryField
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  # Circle
4
6
  #
5
7
  class Circle < GeometryField
6
- attr_accessor :center, :radius
7
-
8
8
  def center
9
9
  Point.new(*self[0])
10
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  class LineString < GeometryField
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  # Point
@@ -6,10 +8,10 @@ module Mongoid
6
8
  include Enumerable
7
9
  attr_accessor :x, :y, :z
8
10
 
9
- def initialize(x, y, z = nil)
10
- @x = x
11
- @y = y
12
- @z = z
11
+ def initialize(lon, lat, alt = nil)
12
+ @x = lon
13
+ @y = lat
14
+ @z = alt
13
15
  end
14
16
 
15
17
  # Object -> Database
@@ -35,11 +37,12 @@ module Mongoid
35
37
 
36
38
  #
37
39
  # Point representation as a Hash
40
+ # Optional param: custom keys.
38
41
  #
39
- # @return [Hash] with { xl => x, yl => y }
42
+ # @return [Hash] with { lng_key => x, lat_key => y }
40
43
  #
41
- def to_hsh(xl = :x, yl = :y)
42
- { xl => x, yl => y }
44
+ def to_hsh(xkey = :x, ykey = :y)
45
+ { xkey => x, ykey => y }
43
46
  end
44
47
  alias to_hash to_hsh
45
48
 
@@ -48,8 +51,8 @@ module Mongoid
48
51
  #
49
52
  # @return [Array] with [self, radius]
50
53
  #
51
- def radius(r = 1)
52
- [ mongoize, r ]
54
+ def radius(r = 1) # rubocop:disable Naming/MethodParameterName
55
+ [mongoize, r]
53
56
  end
54
57
 
55
58
  #
@@ -59,7 +62,7 @@ module Mongoid
59
62
  #
60
63
  # @return [Array] with [self, radius / earth radius]
61
64
  #
62
- def radius_sphere(r = 1, unit = :km)
65
+ def radius_sphere(r = 1, unit = :km) # rubocop:disable Naming/MethodParameterName
63
66
  radius r.to_f / Mongoid::Geospatial.earth_radius[unit]
64
67
  end
65
68
 
@@ -94,7 +97,7 @@ module Mongoid
94
97
  #
95
98
  def to_geo_json
96
99
  # Return a GeoJSON point hash that MongoDB can use
97
- { type: "Point", coordinates: [x, y] }
100
+ { type: 'Point', coordinates: [x, y] }
98
101
  end
99
102
 
100
103
  #
@@ -237,7 +240,7 @@ module Mongoid
237
240
 
238
241
  raise "Hash must contain #{Mongoid::Geospatial::Config::Point.x.inspect}"
239
242
  end
240
- end # << self
241
- end # Point
242
- end # Geospatial
243
- end # Mongoid
243
+ end
244
+ end
245
+ end
246
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  class Polygon < GeometryField
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Geospatial
3
5
  #
@@ -63,7 +65,7 @@ module Mongoid
63
65
  # @param [Numeric] r radius
64
66
  # @return [Array] [point, r] point and radius in mongoid format
65
67
  #
66
- def radius(r = 1)
68
+ def radius(r = 1) # rubocop:disable Naming/MethodParameterName
67
69
  [center, r]
68
70
  end
69
71
 
@@ -75,7 +77,7 @@ module Mongoid
75
77
  # @see Point#radius
76
78
  # @return [Array]
77
79
  #
78
- def radius_sphere(r = 1, unit = :km)
80
+ def radius_sphere(r = 1, unit = :km) # rubocop:disable Naming/MethodParameterName
79
81
  radius r.to_f / Mongoid::Geospatial.earth_radius[unit]
80
82
  end
81
83
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Mongoid fields extension
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Mongoid fields extension
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Mongoid fields extension
3
5
  #
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  # Mongoid Geospatial version
3
5
  module Geospatial
4
- VERSION = '7.0.0'.freeze
6
+ VERSION = '7.1.0'
5
7
  end
6
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'geo_ruby'
2
4
 
3
5
  module Mongoid
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rgeo'
2
4
  require 'mongoid/geospatial/ext/rgeo_spherical_point_impl'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mongoid'
2
4
  require 'active_support/concern' # Explicitly require for `extend ActiveSupport::Concern`
3
5
  require 'mongoid/geospatial/helpers/spatial'
@@ -91,6 +93,38 @@ module Mongoid
91
93
  index({ name => '2dsphere' }, options)
92
94
  end
93
95
 
96
+ #
97
+ # # Queries
98
+ #
99
+ # MongoDB provides the following geospatial query operators.
100
+ #
101
+ # $geoIntersects
102
+ # Selects geometries that intersect with a GeoJSON geometry.
103
+ # The 2dsphere index supports $geoIntersects.
104
+ #
105
+ # $geoWithin
106
+ # Selects geometries within a bounding GeoJSON geometry.
107
+ # The 2dsphere and 2d indexes support $geoWithin.
108
+ #
109
+ # $near
110
+ # Returns geospatial objects in proximity to a point.
111
+ # Requires a geospatial index. The 2dsphere and 2d indexes support $near.
112
+ #
113
+ # $nearSphere
114
+ # Returns geospatial objects in proximity to a point on a sphere.
115
+ # Requires a geospatial index. The 2dsphere and 2d indexes support $nearSphere.
116
+ #
117
+ # # Aggregation
118
+ #
119
+ # MongoDB provides the following geospatial aggregation pipeline stage:
120
+ #
121
+ # $geoNear
122
+ # Returns an ordered stream of documents based on the proximity to a geospatial point.
123
+ # Incorporates the functionality of $match, $sort, and $limit for geospatial data.
124
+ # The output documents include an additional distance field and can include a location identifier field.
125
+ # $geoNear requires a geospatial index.
126
+ #
127
+
94
128
  #
95
129
  # Defines a class method to find the closest document to a given point
96
130
  # using the specified spatial field via the `geoNear` command.
@@ -129,7 +163,7 @@ module Mongoid
129
163
  merged_options[:spherical]
130
164
  else
131
165
  # self.fields uses string keys for field names
132
- field_def = self.fields[field_name.to_s]
166
+ field_def = fields[field_name.to_s]
133
167
  field_def && field_def.options[:sphere]
134
168
  end
135
169
  query_operator = is_spherical ? :near_sphere : :near
@@ -143,15 +177,15 @@ module Mongoid
143
177
  {
144
178
  # Using $geometry for clarity when $maxDistance is used,
145
179
  # which is standard for $near/$nearSphere operators.
146
- "$geometry" => { type: "Point", coordinates: mongoized_coords },
147
- "$maxDistance" => merged_options[:max_distance].to_f
180
+ '$geometry' => { type: 'Point', coordinates: mongoized_coords },
181
+ '$maxDistance' => merged_options[:max_distance].to_f
148
182
  }
149
183
  else
150
184
  mongoized_coords # Simple array [lng, lat] for the operator
151
185
  end
152
186
 
153
187
  # Start with a base criteria, applying an optional filter query
154
- current_criteria = merged_options[:query] ? self.where(merged_options[:query]) : self.all
188
+ current_criteria = merged_options[:query] ? where(merged_options[:query]) : all
155
189
 
156
190
  # Apply the geospatial query. $near and $nearSphere queries return sorted results.
157
191
  current_criteria.where(field_name_sym.send(query_operator) => geo_query_value)
@@ -176,24 +210,122 @@ module Mongoid
176
210
  # Alarm.nearby(my_point_object)
177
211
  #
178
212
  def nearby(coordinates, _options = {})
179
- if self.spatial_fields.empty?
180
- raise "No spatial fields defined for #{self.name} to use with .nearby. " \
213
+ if spatial_fields.empty?
214
+ raise "No spatial fields defined for #{name} to use with .nearby. " \
181
215
  "Mark a field with 'spatial: true' or 'sphere: true'."
182
216
  end
183
217
 
184
- field_name_sym = self.spatial_fields.first.to_sym
185
- field_definition = self.fields[field_name_sym.to_s]
218
+ field_name_sym = spatial_fields.first.to_sym
219
+ field_definition = fields[field_name_sym.to_s]
186
220
 
187
- unless field_definition
188
- raise "Could not find field definition for spatial field: #{field_name_sym}"
189
- end
221
+ raise "Could not find field definition for spatial field: #{field_name_sym}" unless field_definition
190
222
 
191
223
  query_operator = field_definition.options[:sphere] ? :near_sphere : :near
192
224
 
193
225
  criteria.where(field_name_sym.send(query_operator) => coordinates)
194
226
  end
227
+
228
+ # Performs a $geoNear aggregation pipeline stage to find documents near a point,
229
+ # returning them sorted by distance and including the distance.
230
+ #
231
+ # This method is a wrapper around the MongoDB `$geoNear` aggregation stage,
232
+ # which allows for more complex queries and options than the simple `near` or `near_sphere` methods.
233
+ #
234
+ # * But it's not chainable like a standard Mongoid query *
235
+ #
236
+ # @param field_name [String, Symbol] The name of the geospatial field to query.
237
+ # This field must be indexed with a geospatial index (2d or 2dsphere).
238
+ # @param coordinates [Array, Hash, Mongoid::Geospatial::Point] The point to search near.
239
+ # Examples: `[lng, lat]`, `{ type: 'Point', coordinates: [lng, lat] }`, a `Mongoid::Geospatial::Point` object.
240
+ # @param options [Hash] Options for the $geoNear stage.
241
+ # Key options include:
242
+ # - `:spherical` [Boolean] If true, calculates distances using spherical geometry. Defaults to `false`.
243
+ # - `:distanceField` [String] Name of the output field that will contain the distance. Defaults to `'distance'`.
244
+ # - `:maxDistance` [Numeric] The maximum distance from the center point that documents can be.
245
+ # For spherical queries, specify distance in meters. For 2d queries, in the same units as coordinates.
246
+ # - `:minDistance` [Numeric] The minimum distance. (MongoDB 2.6+)
247
+ # - `:query` [Hash] Limits the results to the documents that match the query.
248
+ # - `:limit` [Integer] The maximum number of documents to return (applied as a separate `$limit` pipeline stage).
249
+ # - `:distanceMultiplier` [Numeric] A factor to multiply all distances returned by the query.
250
+ # - `:includeLocs` [String] Specifies the name of the output field that identifies the location used to calculate the distance.
251
+ # This is useful when the queried field contains multiple locations (e.g., an array of points) or complex GeoJSON
252
+ # geometries (e.g., a Polygon), as it shows which specific point was used for the distance calculation.
253
+ # Example: `includeLocs: 'matchedPoint'` would add a `matchedPoint` field to each output document.
254
+ #
255
+ # @return [Array<Mongoid::Document>] An array of instantiated Mongoid documents.
256
+ # Each document will include its original fields plus any fields added by the `$geoNear` stage,
257
+ # such as the field specified by `:distanceField` (e.g., `document.distance`) and `:includeLocs`.
258
+ # These additional fields are accessible as dynamic attributes on the model instances.
259
+ #
260
+ # @raise [ArgumentError] If coordinates cannot be mongoized.
261
+ #
262
+ # Example:
263
+ # # Find places near [10, 20], using spherical calculations, up to 5km away
264
+ # Place.geo_near(:location, [10, 20],
265
+ # spherical: true,
266
+ # maxDistance: 5000, # 5 kilometers in meters
267
+ # distanceField: 'dist.calculated',
268
+ # query: { category: 'restaurant' },
269
+ # limit: 10)
270
+ #
271
+ # # Iterate over results
272
+ # Place.geo_near(:location, [10, 20], spherical: true).each do |place|
273
+ # puts "#{place.name} is #{place.distance} meters away." # Assumes distanceField is 'distance'
274
+ # end
275
+ #
276
+ def geo_near(field_name, coordinates, options = {})
277
+ mongoized_coords = Mongoid::Geospatial::Point.mongoize(coordinates)
278
+
279
+ raise ArgumentError, "Invalid coordinates provided: #{coordinates.inspect}" unless mongoized_coords
280
+
281
+ # User-provided options. Work with a copy.
282
+ user_options = options.dup
283
+ limit_value = user_options.delete(:limit) # Handled by a separate pipeline stage
284
+
285
+ # Core $geoNear parameters derived from method arguments, these are not overrideable by user_options.
286
+ geo_near_core_params = {
287
+ key: field_name.to_s,
288
+ near: mongoized_coords
289
+ }
290
+
291
+ # Defaultable $geoNear parameters. User options will override these.
292
+ geo_near_defaultable_params = {
293
+ distanceField: 'distance',
294
+ spherical: false # Default to planar (2d) calculations
295
+ }
296
+
297
+ # Merge user options over defaults, then ensure core parameters are set.
298
+ geo_near_stage_options = geo_near_defaultable_params.merge(user_options).merge(geo_near_core_params)
299
+
300
+ # Ensure :spherical is a strict boolean (true/false).
301
+ # If user_options provided :spherical, it's already set. If not, the default is used.
302
+ # This line ensures the final value is strictly true or false, not just truthy/falsy.
303
+ geo_near_stage_options[:spherical] = !geo_near_stage_options[:spherical].nil?
304
+
305
+ # Note on performance:
306
+ # $geoNear is an aggregation pipeline stage. For simple proximity queries,
307
+ # it might exhibit slightly higher "real" time (wall-clock time) in benchmarks
308
+ # compared to direct query operators like $near or $nearSphere. This is often
309
+ # due to the inherent overhead of the aggregation framework versus a direct query.
310
+ # However, $geoNear offers more capabilities, such as returning the distance
311
+ # (distanceField), distanceMultiplier, includeLocs, and integrating with other
312
+ # aggregation stages, which are not available with $near/$nearSphere.
313
+ pipeline = [{ '$geoNear' => geo_near_stage_options }]
314
+
315
+ # Add $limit stage if limit_value was provided
316
+ pipeline << { '$limit' => limit_value.to_i } if limit_value
317
+
318
+ # Execute the aggregation pipeline
319
+ collection.aggregate(pipeline)
320
+
321
+ # Don't instantiate results here.
322
+ # aggregated_results = collection.aggregate(pipeline)
323
+ # Map the raw Hash results from aggregation to Mongoid model instances.
324
+ # Mongoid's #instantiate method correctly handles creating model objects
325
+ # and assigning attributes, including dynamic ones like the distanceField.
326
+ # aggregated_results.map { |attrs| instantiate(attrs) }
327
+ end
195
328
  end
196
329
  end
197
330
  end
198
-
199
331
  require 'mongoid/geospatial/config'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-geospatial
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Ong
@@ -32,20 +32,8 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - ".coveralls.yml"
36
- - ".gitignore"
37
- - ".hound.yml"
38
- - ".rspec"
39
- - ".rubocop.yml"
40
- - ".travis.yml"
41
- - CHANGELOG.md
42
- - CONTRIBUTING.md
43
- - Gemfile
44
- - Guardfile
45
35
  - MIT-LICENSE
46
36
  - README.md
47
- - RELEASING.md
48
- - Rakefile
49
37
  - lib/mongoid/geospatial.rb
50
38
  - lib/mongoid/geospatial/config.rb
51
39
  - lib/mongoid/geospatial/config/point.rb
@@ -62,40 +50,11 @@ files:
62
50
  - lib/mongoid/geospatial/version.rb
63
51
  - lib/mongoid/geospatial/wrappers/georuby.rb
64
52
  - lib/mongoid/geospatial/wrappers/rgeo.rb
65
- - mongoid-geospatial.gemspec
66
- - spec/bench
67
- - spec/models/address.rb
68
- - spec/models/alarm.rb
69
- - spec/models/bar.rb
70
- - spec/models/bus.rb
71
- - spec/models/event.rb
72
- - spec/models/farm.rb
73
- - spec/models/person.rb
74
- - spec/models/phone.rb
75
- - spec/models/place.rb
76
- - spec/models/river.rb
77
- - spec/mongoid.yml
78
- - spec/mongoid/geospatial/config_spec.rb
79
- - spec/mongoid/geospatial/fields/box_spec.rb
80
- - spec/mongoid/geospatial/fields/circle_spec.rb
81
- - spec/mongoid/geospatial/fields/line_string_spec.rb
82
- - spec/mongoid/geospatial/fields/point_spec.rb
83
- - spec/mongoid/geospatial/fields/polygon_spec.rb
84
- - spec/mongoid/geospatial/geospatial_spec.rb
85
- - spec/mongoid/geospatial/helpers/core_spec.rb
86
- - spec/mongoid/geospatial/helpers/delegate_spec.rb
87
- - spec/mongoid/geospatial/helpers/spatial_spec.rb
88
- - spec/mongoid/geospatial/helpers/sphere_spec.rb
89
- - spec/mongoid/geospatial/wrappers/georuby_spec.rb
90
- - spec/mongoid/geospatial/wrappers/rgeo_spec.rb
91
- - spec/spec_helper.rb
92
- - spec/support/authentication.rb
93
- - spec/support/mongod.conf
94
- - spec/support/mongoid.yml
95
53
  homepage: https://github.com/mongoid/mongoid-geospatial
96
54
  licenses:
97
55
  - MIT
98
- metadata: {}
56
+ metadata:
57
+ rubygems_mfa_required: 'true'
99
58
  rdoc_options: []
100
59
  require_paths:
101
60
  - lib
@@ -103,7 +62,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
62
  requirements:
104
63
  - - ">="
105
64
  - !ruby/object:Gem::Version
106
- version: '0'
65
+ version: 3.1.0
107
66
  required_rubygems_version: !ruby/object:Gem::Requirement
108
67
  requirements:
109
68
  - - ">="
@@ -113,33 +72,4 @@ requirements: []
113
72
  rubygems_version: 3.6.7
114
73
  specification_version: 4
115
74
  summary: Mongoid Extension that simplifies MongoDB Geospatial Operations.
116
- test_files:
117
- - spec/bench
118
- - spec/models/address.rb
119
- - spec/models/alarm.rb
120
- - spec/models/bar.rb
121
- - spec/models/bus.rb
122
- - spec/models/event.rb
123
- - spec/models/farm.rb
124
- - spec/models/person.rb
125
- - spec/models/phone.rb
126
- - spec/models/place.rb
127
- - spec/models/river.rb
128
- - spec/mongoid.yml
129
- - spec/mongoid/geospatial/config_spec.rb
130
- - spec/mongoid/geospatial/fields/box_spec.rb
131
- - spec/mongoid/geospatial/fields/circle_spec.rb
132
- - spec/mongoid/geospatial/fields/line_string_spec.rb
133
- - spec/mongoid/geospatial/fields/point_spec.rb
134
- - spec/mongoid/geospatial/fields/polygon_spec.rb
135
- - spec/mongoid/geospatial/geospatial_spec.rb
136
- - spec/mongoid/geospatial/helpers/core_spec.rb
137
- - spec/mongoid/geospatial/helpers/delegate_spec.rb
138
- - spec/mongoid/geospatial/helpers/spatial_spec.rb
139
- - spec/mongoid/geospatial/helpers/sphere_spec.rb
140
- - spec/mongoid/geospatial/wrappers/georuby_spec.rb
141
- - spec/mongoid/geospatial/wrappers/rgeo_spec.rb
142
- - spec/spec_helper.rb
143
- - spec/support/authentication.rb
144
- - spec/support/mongod.conf
145
- - spec/support/mongoid.yml
75
+ test_files: []
data/.coveralls.yml DELETED
@@ -1 +0,0 @@
1
- service_name: travis-ci