Permalink
Browse files

[Closes #142] Adds support for filtering by bounding box

  • Loading branch information...
1 parent fc774d0 commit 5c7aa948244f11840982f0f3d5896e9f0ee41195 @alindeman alindeman committed Dec 16, 2011
View
@@ -499,6 +499,29 @@ Post.search do
end
```
+#### Filter By Radius (inexact with bbox)
+
+**TODO: Yet to be implemented**
+
+```ruby
+# Searches posts within 100 kilometers of (32, -68) with `bbox`. This is
+# an approximation so searches run quicker, but it may include other
+# points that are slightly outside of the required distance
+Post.search do
+ with(:location).in_radius(32, -68, 100, :bbox => true)
+end
+```
+
+#### Filter By Bounding Box
+
+```ruby
+# Searches posts within the bounding box defined by the corners (45,
+# -94) to (46, -93)
+Post.search do
+ with(:location).in_bounding_box([45, -94], [46, -93])
+end
+```
+
#### Sort By Distance
```ruby
@@ -133,6 +133,20 @@ def near(lat, lng, options = {})
def in_radius(lat, lon, radius)
@query.add_geo(Sunspot::Query::Geofilt.new(@field, lat, lon, radius))
end
+
+ #
+ # Performs a query that is filtered by a bounding box
+ #
+ # ==== Parameters
+ #
+ # :first_corner<Array>::
+ # First corner (expressed as an array `[latitude, longitude]`)
+ # :second_corner<Array>::
+ # Second corner (expressed as an array `[latitude, longitude]`)
+ #
+ def in_bounding_box(first_corner, second_corner)
+ @query.add_geo(Sunspot::Query::Bbox.new(@field, first_corner, second_corner))
+ end
end
end
end
@@ -1,7 +1,7 @@
%w(filter abstract_field_facet connective boost_query date_field_facet dismax
field_facet highlighting pagination restriction common_query
- standard_query more_like_this more_like_this_query geo geofilt query_facet scope
- sort sort_composite text_field_boost function_query
+ standard_query more_like_this more_like_this_query geo geofilt bbox query_facet
+ scope sort sort_composite text_field_boost function_query
composite_fulltext field_group).each do |file|
require(File.join(File.dirname(__FILE__), 'query', file))
end
@@ -0,0 +1,15 @@
+module Sunspot
+ module Query
+ class Bbox
+ def initialize(field, first_corner, second_corner)
+ @field, @first_corner, @second_corner = field, first_corner, second_corner
+ end
+
+ def to_params
+ filter = "#{@field.indexed_name}:[#{@first_corner.join(",")} TO #{@second_corner.join(",")}]"
+
+ {:fq => filter}
+ end
+ end
+ end
+end
@@ -8,4 +8,12 @@
connection.should have_last_search_including(:fq, "{!geofilt sfield=coordinates_new_ll pt=23,-46 d=100}")
end
+
+ it 'filters by bounding box' do
+ search do
+ with(:coordinates_new).in_bounding_box([45, -94], [46, -93])
+ end
+
+ connection.should have_last_search_including(:fq, "coordinates_new_ll:[45,-94 TO 46,-93]")
+ end
end
@@ -10,7 +10,7 @@
Sunspot.index!(@post)
end
- it "matches posts with the radius" do
+ it "matches posts within the radius" do
results = Sunspot.search(Post) {
with(:coordinates_new).in_radius(32, -68, 1)
}.results
@@ -27,6 +27,32 @@
end
end
+ describe "filtering by bounding box" do
+ before :all do
+ Sunspot.remove_all
+
+ @post = Post.new(:title => "Howdy",
+ :coordinates => Sunspot::Util::Coordinates.new(32, -68))
+ Sunspot.index!(@post)
+ end
+
+ it "matches post within the bounding box" do
+ results = Sunspot.search(Post) {
+ with(:coordinates_new).in_bounding_box [31, -69], [33, -67]
+ }.results
+
+ results.should include(@post)
+ end
+
+ it "filters out posts not in the bounding box" do
+ results = Sunspot.search(Post) {
+ with(:coordinates_new).in_bounding_box [20, -70], [21, -69]
+ }.results
+
+ results.should_not include(@post)
+ end
+ end
+
describe "ordering by geodist" do
before :all do
Sunspot.remove_all

0 comments on commit 5c7aa94

Please sign in to comment.