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, 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.



1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
# File 'lib/parse/query/constraints.rb', line 1797

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:



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

constraint_keyword :$nearSphere