Class: Parse::Constraint::NearSphereQueryConstraint

Inherits:
Parse::Constraint show all
Defined in:
lib/parse/query/constraints.rb

Overview

TODO:

Add support $maxDistanceInKilometers (for kms) and $maxDistanceInRadians (for radian angle).

Equivalent to the $nearSphere Parse query operation. This is only applicable if the field is of type GeoPoint. This will query Parse and return a list of results ordered by distance with the nearest object being first.

q.where :field.near => geopoint

geopoint = Parse::GeoPoint.new(30.0, -20.0) PlaceObject.all :location.near => geopoint If you wish to constrain the geospatial query to a maximum number of miles, you can utilize the max_miles method on a Parse::GeoPoint object. This is equivalent to the $maxDistanceInMiles constraint used with $nearSphere.

q.where :field.near => geopoint.max_miles(distance) # or provide a triplet includes max miles constraint q.where :field.near => [lat, lng, miles]

geopoint = Parse::GeoPoint.new(30.0, -20.0) PlaceObject.all :location.near => geopoint.max_miles(10)

Constant Summary collapse

KM_PER_RADIAN =

Conversion factors mirror WithinSphereQueryConstraint so the cap below is unit-agnostic.

6371.0
MILES_PER_RADIAN =
3958.8
MAX_RADIANS =

Whole-sphere cap (π radians ≈ 6371π km ≈ 3958.8π miles). A $nearSphere with a larger $maxDistanceIn* defeats the 2dsphere early-termination optimization and degenerates to a full geo scan.

Math::PI

Instance Attribute Summary

Attributes inherited from Parse::Constraint

#operand, #operation, #operator, #value

Instance Method Summary collapse

Methods inherited from Parse::Constraint

#as_json, constraint_keyword, create, formatted_value, #formatted_value, #initialize, #key, #precedence, #regex_unicode_option, register, #to_s

Constructor Details

This class inherits a constructor from Parse::Constraint

Instance Method Details

#buildHash

Returns the compiled constraint.

Returns:

  • (Hash)

    the compiled constraint.



1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
# File 'lib/parse/query/constraints.rb', line 1821

def build
  point = formatted_value
  max_distance = nil
  unit = :miles
  if point.is_a?(Array) && point.count > 1
    if point.count >= 3
      max_distance = point[2]
      # max_kilometers / max_radians tag the array with their unit
      # symbol in the 4th slot so we can dispatch to the right
      # Parse operator key. max_miles leaves slot 3 nil and the
      # default :miles applies.
      unit = point[3] if [:km, :radians].include?(point[3])
    end
    point = { __type: "GeoPoint", latitude: point[0], longitude: point[1] }
  end
  if max_distance.present? && max_distance > 0
    # Cap radius at whole-sphere coverage (π radians) regardless
    # of the chosen unit. Without this cap, an attacker-controlled
    # `max_*` (e.g. user-supplied km) can submit a huge value and
    # force a full-collection scan.
    radians_for_check =
      case unit
      when :km then max_distance.to_f / KM_PER_RADIAN
      when :radians then max_distance.to_f
      else max_distance.to_f / MILES_PER_RADIAN
      end
    if radians_for_check > MAX_RADIANS
      raise ArgumentError, "[Parse::Query] `near` max distance #{max_distance} #{unit} " \
                           "(#{radians_for_check} radians) exceeds whole-sphere coverage " \
                           "(π radians). A radius that large defeats the 2dsphere index " \
                           "and degenerates $nearSphere into a full collection scan."
    end

    distance_key =
      case unit
      when :km then :$maxDistanceInKilometers
      when :radians then :$maxDistance
      else :$maxDistanceInMiles
      end
    return { @operation.operand => { key => point, distance_key => max_distance.to_f } }
  end
  { @operation.operand => { key => point } }
end

#nearNearSphereQueryConstraint

A registered method on a symbol to create the constraint. Maps to Parse operator "$nearSphere".

Examples:

q.where :field.near => geopoint
q.where :field.near => geopoint.max_miles(distance)
q.where :field.near => geopoint.max_kilometers(distance)

Returns:



1807
# File 'lib/parse/query/constraints.rb', line 1807

constraint_keyword :$nearSphere