Class: Parse::Constraint::WithinSphereQueryConstraint

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

Overview

Equivalent to the ‘$geoWithin` Parse query operation with `$centerSphere` subconstraint. Filters a GeoPoint column by membership in a circular region defined by a center point and a radius. Unlike `:field.near => geopoint.max_*(N)`, this constraint does NOT order results by distance, which makes it cheap and composable inside `$or` branches and aggregation pipelines.

The radius is in radians at the wire level. For convenience the DSL accepts an Array tuple ‘[geopoint, distance, unit]` where `unit` may be `:radians` (default), `:km` / `:kilometers`, or `:miles`; the SDK converts to radians using mean-Earth-radius 6371 km / 3958.8 mi.

q.where :location.within_sphere => [center, 5, :km]
q.where :location.within_sphere => [center, 10, :miles]
q.where :location.within_sphere => [center, 0.001]            # radians

Version:

  • 4.4.0 (requires Parse Server with ‘$centerSphere` support)

Constant Summary collapse

KM_PER_RADIAN =
6371.0
MILES_PER_RADIAN =
3958.8
MAX_RADIANS =

Whole-sphere radius. ‘$centerSphere` with a radius greater than π radians covers the entire sphere — a query that returns every document in the collection and trivially defeats any `2dsphere` index. Cap here so attacker-controlled radii (e.g. URL params forwarded into the constraint) can’t degenerate into a full-collection 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.



1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
# File 'lib/parse/query/constraints.rb', line 1955

def build
  value = formatted_value
  unless value.is_a?(Array) && value.length >= 2
    raise ArgumentError, "[Parse::Query] Invalid value for `within_sphere` constraint: " \
                         "expected [geopoint, distance, unit?]."
  end

  point, distance, unit = value[0], value[1], (value[2] || :radians)
  unless point.is_a?(Parse::GeoPoint)
    raise ArgumentError, "[Parse::Query] `within_sphere` first element must be a Parse::GeoPoint."
  end
  unless distance.is_a?(Numeric) && distance > 0
    raise ArgumentError, "[Parse::Query] `within_sphere` distance must be a positive number."
  end

  radians =
    case unit
    when :radians then distance.to_f
    when :km, :kilometers then distance.to_f / KM_PER_RADIAN
    when :miles then distance.to_f / MILES_PER_RADIAN
    else
      raise ArgumentError, "[Parse::Query] `within_sphere` unit must be :radians, :km, or :miles."
    end

  if radians > MAX_RADIANS
    raise ArgumentError, "[Parse::Query] `within_sphere` radius #{distance} #{unit} " \
                         "(#{radians} radians) exceeds whole-sphere coverage (π radians). " \
                         "A radius that large covers the entire sphere and degenerates " \
                         "$centerSphere into a full-collection scan."
  end

  # MongoDB's $centerSphere expects [longitude, latitude]
  # (GeoJSON convention), not Parse's [latitude, longitude] order.
  center = [point.longitude, point.latitude]
  # `$centerSphere` is a native MongoDB geo operator, not a
  # documented Parse Server REST find operator. Mark this
  # constraint mongo-direct-only so the query layer auto-routes
  # to {Parse::Query#results_direct}; callers without a mongo
  # connection or master-key/scoped auth will get
  # `MongoDirectRequired` rather than a silently-wrong REST
  # result.
  {
    @operation.operand => { :$geoWithin => { :$centerSphere => [center, radians] } },
    "__mongo_direct_only" => true,
  }
end

#within_sphereWithinSphereQueryConstraint

A registered method on a symbol to create the constraint. Maps to Parse operator “$geoWithin” with “$centerSphere” subconstraint.

Examples:

q.where :location.within_sphere => [center_geopoint, 5, :km]

Returns:



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

constraint_keyword :$geoWithin