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.



1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
# File 'lib/parse/query/constraints.rb', line 1768

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:



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

constraint_keyword :$nearSphere