Module: Mongoid::Geospatial::ClassMethods
- Defined in:
- lib/mongoid/geospatial.rb
Overview
Methods applied to Document’s class
Instance Method Summary collapse
-
#nearby(coordinates, _options = {}) ⇒ Mongoid::Criteria
Provides a convenient way to find documents near a given set of coordinates.
-
#spatial_index(name, options = {}) ⇒ Object
Creates a 2d spatial index for the given field.
-
#spatial_scope(field_name, default_geo_near_options = {}) ⇒ Object
Defines a class method to find the closest document to a given point using the specified spatial field via the
geoNearcommand. -
#spherical_index(name, options = {}) ⇒ Object
Creates a 2dsphere index for the given field, suitable for spherical geometry calculations.
Instance Method Details
#nearby(coordinates, _options = {}) ⇒ Mongoid::Criteria
Provides a convenient way to find documents near a given set of coordinates. It automatically uses the first spatial field defined in the model and determines whether to use a planar (.near) or spherical (.near_sphere) query based on the field’s definition options (‘spatial: true` vs `sphere: true`).
Example:
Bar.nearby([10, 20])
Alarm.nearby(my_point_object)
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/mongoid/geospatial.rb', line 178 def nearby(coordinates, = {}) if self.spatial_fields.empty? raise "No spatial fields defined for #{self.name} to use with .nearby. " \ "Mark a field with 'spatial: true' or 'sphere: true'." end field_name_sym = self.spatial_fields.first.to_sym field_definition = self.fields[field_name_sym.to_s] unless field_definition raise "Could not find field definition for spatial field: #{field_name_sym}" end query_operator = field_definition.[:sphere] ? :near_sphere : :near criteria.where(field_name_sym.send(query_operator) => coordinates) end |
#spatial_index(name, options = {}) ⇒ Object
Creates a 2d spatial index for the given field.
78 79 80 81 |
# File 'lib/mongoid/geospatial.rb', line 78 def spatial_index(name, = {}) spatial_fields_indexed << name index({ name => '2d' }, ) end |
#spatial_scope(field_name, default_geo_near_options = {}) ⇒ Object
Defines a class method to find the closest document to a given point using the specified spatial field via the geoNear command.
Example:
class Place
include Mongoid::Document
include Mongoid::Geospatial
field :location, type: Array
spherical_index :location # Assumes a 2dsphere index for spherical queries
spatial_scope :location, spherical: true # Default to spherical for this scope
end
Place.closest_to_location([lon, lat]) # Finds the single closest place
Place.closest_to_location([lon, lat], max_distance: 500) # Override/add options
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/mongoid/geospatial.rb', line 115 def spatial_scope(field_name, = {}) method_name = :"closest_to_#{field_name}" field_name_sym = field_name.to_sym # key_name = field_name.to_s # Original geoNear used 'key' for field name singleton_class.class_eval do define_method(method_name) do |coordinates, = {}| # `coordinates` should be [lon, lat] or a GeoJSON Point hash # `self` here is the class (e.g., Bar) = .merge() # Determine if spherical based on options or field definition is_spherical = if .key?(:spherical) [:spherical] else # self.fields uses string keys for field names field_def = self.fields[field_name.to_s] field_def && field_def.[:sphere] end query_operator = is_spherical ? :near_sphere : :near # Prepare the value for the geospatial operator # Mongoid::Geospatial::Point.mongoize ensures coordinates are in [lng, lat] array format # from various input types (Point object, array, string, hash). mongoized_coords = Mongoid::Geospatial::Point.mongoize(coordinates) geo_query_value = if [:max_distance] { # Using $geometry for clarity when $maxDistance is used, # which is standard for $near/$nearSphere operators. "$geometry" => { type: "Point", coordinates: mongoized_coords }, "$maxDistance" => [:max_distance].to_f } else mongoized_coords # Simple array [lng, lat] for the operator end # Start with a base criteria, applying an optional filter query current_criteria = [:query] ? self.where([:query]) : self.all # Apply the geospatial query. $near and $nearSphere queries return sorted results. current_criteria.where(field_name_sym.send(query_operator) => geo_query_value) end end end |
#spherical_index(name, options = {}) ⇒ Object
Creates a 2dsphere index for the given field, suitable for spherical geometry calculations.
89 90 91 92 |
# File 'lib/mongoid/geospatial.rb', line 89 def spherical_index(name, = {}) spatial_fields_indexed << name index({ name => '2dsphere' }, ) end |