mongoid_geospatial 2.3.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,7 +3,6 @@ Mongoid Geospatial
3
3
 
4
4
  A Mongoid Extension that simplifies the use of MongoDB spatial features.
5
5
 
6
-
7
6
  ** On beta again **
8
7
 
9
8
  Removing some trash, improving and adding support for RGeo and GeoRuby.
@@ -25,98 +24,26 @@ You can also use an external Geometric/Spatial alongside.
25
24
  # Gemfile
26
25
  gem 'mongoid_geospatial'
27
26
 
28
-
29
27
  # A place to illustrate Point, Line and Polygon
30
28
  class Place
31
29
  include Mongoid::Document
30
+
31
+ # Include the module
32
32
  include Mongoid::Geospatial
33
33
 
34
+ # Just like mongoid,
34
35
  field :name, type: String
36
+ # define your field, but choose a geometry type:
35
37
  field :location, type: Point, :spatial => true
36
38
  field :route, type: Linestring
37
39
  field :area, type: Polygon
40
+
41
+ # If your are going to query on your points, don't forget to index:
42
+ spatial_index :location
43
+
38
44
  end
39
45
 
40
46
 
41
- Geometry Helpers
42
- ----------------
43
-
44
- We currently support GeoRuby and RGeo.
45
- If you require one of those, a #to_geo method will be available to all
46
- spatial fields, returning the external library corresponding object.
47
- To illustrate:
48
-
49
- class Person
50
- include Mongoid::Document
51
- include Mongoid::Geospatial
52
-
53
- field :location, type: Point
54
- end
55
-
56
- me = Person.new(location: [8, 8])
57
-
58
- # Example with GeoRuby
59
- point.class # Mongoid::Geospatial::Point
60
- point.to_geo.class # GeoRuby::SimpleFeatures::Point
61
-
62
- # Example with RGeo
63
- point.class # Mongoid::Geospatial::Point
64
- point.to_geo.class # RGeo::Geographic::SphericalPointImpl
65
-
66
-
67
- Configure
68
- ----------------
69
-
70
- Assemble it as you need (use a initializer file):
71
-
72
- With RGeo
73
-
74
- Mongoid::Geospatial.use_rgeo
75
- # Optional
76
- # Mongoid::Geospatial.factory = RGeo::Geographic.spherical_factory
77
-
78
- With GeoRuby
79
-
80
- Mongoid::Geospatial.use_georuby
81
-
82
- Defaults (change if you know what you're doing)
83
-
84
- Mongoid::Geospatial.lng_symbol = :x
85
- Mongoid::Geospatial.lat_symbol = :y
86
- Mongoid::Geospatial.earth_radius = EARTH_RADIUS
87
-
88
-
89
-
90
- Model Setup
91
- -----------
92
-
93
- You can create Point, Line, Circle, Box and Polygon on your models:
94
-
95
-
96
- class River
97
- include Mongoid::Document
98
- include Mongoid::Geospatial
99
-
100
- field :name, type: String
101
- field :length, type: Integer
102
- field :discharge, type: Integer
103
-
104
- field :source, type: Point, spatial: true
105
- field :mouth, type: Point, spatial: true
106
- field :course, type: Line
107
- field :boundings, type: Box
108
-
109
- # spatial indexing
110
- spatial_index :mouth
111
-
112
- # default mongodb options
113
- spatial_index :mouth, {bit: 24, min: -180, max: 180}
114
- end
115
-
116
-
117
- Use
118
- ---
119
-
120
47
  Generate indexes on MongoDB:
121
48
 
122
49
 
@@ -126,6 +53,10 @@ Generate indexes on MongoDB:
126
53
  Points
127
54
  ------
128
55
 
56
+ Currently, MongoDB supports query operations on 2D points only, so that's
57
+ what this lib does. All geometries apart from points are just arrays
58
+ in the database. Here's is how you can input a point as:
59
+
129
60
  * an unordered hash with the lat long string keys defined when setting the field (only applies for setting the field)
130
61
  * longitude latitude array in that order - [long,lat] ([x, y])
131
62
  * an unordered hash with latitude key(:lat, :latitude) and a longitude key(:lon, :long, :lng, :longitude)
@@ -150,10 +81,18 @@ We store data in the DB as a [lng,lat] array then reformat when it is returned t
150
81
  Now to access this spatial information we can do this
151
82
 
152
83
  hudson.mouth # => [-74.026667, 40.703056]
84
+
85
+ If you need a hash
86
+
87
+ hudson.mouth.to_hsh # => { x: -74.026667, y: 40.703056 }
88
+
89
+ If you are using GeoRuby or RGeo
90
+
91
+ hudson.mouth.to_geo # => NiceGeolib::Point
153
92
 
154
93
  Distance and other geometrical calculations are delegated to the external
155
94
  library you choosed. More info about using RGeo or GeoRuby below.
156
- Some built in helpers:
95
+ Some built in helpers for mongoid queries:
157
96
 
158
97
  # Returns middle point + radius
159
98
  # Useful to search #within_circle
@@ -165,6 +104,12 @@ Some built in helpers:
165
104
  hudson.mounth.to_hsh(:lon, :lat) # {:lon => -74.., :lat => 40..}
166
105
 
167
106
 
107
+ And for polygons and lines:
108
+
109
+ house.area.bbox # Returns polygon bounding_box (envelope)
110
+ house.area.center # Returns calculate middle point
111
+
112
+
168
113
  Query
169
114
  --------
170
115
 
@@ -178,30 +123,150 @@ All MongoDB queries are handled by Mongoid.
178
123
  You can use Geometry instance directly on any query:
179
124
 
180
125
  * near
126
+ * Bar.near(location: person.house)
181
127
  * Bar.where(:location.near => person.house)
128
+
182
129
 
183
130
  * near_sphere
131
+ * Bar.near_sphere(location: person.house)
184
132
  * Bar.where(:location.near_sphere => person.house)
185
133
 
134
+
186
135
  * within_box
187
- * Bar.where(:location.within_box => hood.area)
136
+ * Bar.within_box(location: hood.area)
137
+
188
138
 
189
139
  * within_circle
190
- * Bar.where(:location.within_box => hood.area)
140
+ * Bar.within_circle(location: hood.area)
141
+
191
142
 
192
143
  * within_circle_sphere
193
- * Bar.where(:location.within_circle_sphere => hood.area)
144
+ * Bar.within_circle_sphere(location: hood.area)
145
+
194
146
 
195
147
  * within_polygon
196
- * Bar.where(:location.within_polygon => city.area)
148
+ * Bar.within_polygon(location: city.area)
149
+
150
+
151
+ External Libraries
152
+ ------------------
153
+
154
+ Use RGeo?
155
+ https://github.com/dazuma/rgeo
156
+
157
+ RGeo is a Ruby wrapper for Proj/GEOS.
158
+ It's perfect when you need to work with complex calculations and projections.
159
+ It'll require more stuff installed to compile/work.
160
+
161
+
162
+ Use GeoRuby?
163
+ https://github.com/nofxx/geo_ruby
164
+
165
+ GeoRuby is a pure Ruby Geometry Library.
166
+ It's perfect if you want simple calculations and/or keep your stack in pure ruby.
167
+ Albeit not full featured in maths it has a handful of methods and good import/export helpers.
168
+
169
+ Use Nothing?
170
+
171
+ This lib won't stand in your way.
172
+ Write your own wrapper if you want.
173
+
174
+
175
+ Geometry Helpers
176
+ ----------------
177
+
178
+ We currently support GeoRuby and RGeo.
179
+ If you require one of those, a #to_geo method will be available to all
180
+ spatial fields, returning the external library corresponding object.
181
+ To illustrate:
182
+
183
+ class Person
184
+ include Mongoid::Document
185
+ include Mongoid::Geospatial
186
+
187
+ field :location, type: Point
188
+ end
189
+
190
+ me = Person.new(location: [8, 8])
191
+
192
+ # Example with GeoRuby
193
+ point.class # Mongoid::Geospatial::Point
194
+ point.to_geo.class # GeoRuby::SimpleFeatures::Point
195
+
196
+ # Example with RGeo
197
+ point.class # Mongoid::Geospatial::Point
198
+ point.to_geo.class # RGeo::Geographic::SphericalPointImpl
199
+
200
+
201
+ Configure
202
+ ----------------
203
+
204
+ Assemble it as you need (use a initializer file):
205
+
206
+ With RGeo
207
+
208
+ Mongoid::Geospatial.use_rgeo
209
+ # Optional
210
+ # Mongoid::Geospatial.factory = RGeo::Geographic.spherical_factory
211
+
212
+
213
+ With GeoRuby
214
+
215
+ Mongoid::Geospatial.use_georuby
216
+
217
+
218
+ Defaults (change if you know what you're doing)
219
+
220
+ Mongoid::Geospatial.lng_symbol = :x
221
+ Mongoid::Geospatial.lat_symbol = :y
222
+ Mongoid::Geospatial.earth_radius = EARTH_RADIUS
223
+
224
+
225
+
226
+ Model Setup
227
+ -----------
228
+
229
+ You can create Point, Line, Circle, Box and Polygon on your models:
230
+
231
+
232
+ class CrazyGeom
233
+ include Mongoid::Document
234
+ include Mongoid::Geospatial
235
+
236
+ field :location, type: Point
237
+
238
+ field :route, type: Line
239
+ field :area, type: Polygon
240
+
241
+ field :square, type: Box
242
+ field :around, type: Circle
243
+
244
+ # spatial indexing
245
+ spatial_index :mouth
246
+
247
+ # default mongodb options
248
+ spatial_index :mouth, {bit: 24, min: -180, max: 180}
249
+
250
+ # query by location
251
+ spatial_scope :location
252
+ end
253
+
254
+
255
+
256
+ Nearby
257
+ ------
197
258
 
259
+ You can add a `spatial_scope` on your models. So you can query:
198
260
 
199
- Class Methods
200
- -------------
261
+ Bar.nearby(my.location)
262
+
263
+ instead of
201
264
 
202
- Some method are added to your class when you define a field as spatial.
265
+ Bar.near(location: my.location)
266
+
267
+ Good when you're drunk. Just add to your model:
203
268
 
204
- field :location, type: Point, spatial: true
269
+ spatial_scope :<field>
205
270
 
206
271
 
207
272
 
@@ -25,8 +25,8 @@ module Mongoid
25
25
  [center, r]
26
26
  end
27
27
 
28
- def radius_sphere r = 1
29
- [center, r.to_f/Mongoid::Geospatial.earth_radius[:km]]
28
+ def radius_sphere r = 1, unit = :km
29
+ radius r.to_f/Mongoid::Geospatial.earth_radius[unit]
30
30
  end
31
31
 
32
32
 
@@ -1,6 +1,7 @@
1
1
  module Mongoid
2
2
  module Geospatial
3
3
  class Point
4
+ include Enumerable
4
5
  attr_accessor :x, :y
5
6
 
6
7
  def initialize(x=nil, y=nil)
@@ -18,6 +19,11 @@ module Mongoid
18
19
  mongoize[args]
19
20
  end
20
21
 
22
+ def each
23
+ yield x
24
+ yield y
25
+ end
26
+
21
27
  def to_hsh xl = :x, yl = :y
22
28
  {xl => x, yl => y}
23
29
  end
@@ -58,7 +64,7 @@ module Mongoid
58
64
 
59
65
  # Database -> Object
60
66
  def demongoize(object)
61
- # return unless object && !object.empty?
67
+ return unless object
62
68
  Point.new(*object)
63
69
  end
64
70
 
@@ -26,7 +26,7 @@ module Mongoid
26
26
  @@earth_radius = EARTH_RADIUS.dup
27
27
 
28
28
  included do
29
- attr_accessor :geo
29
+ # attr_accessor :geo
30
30
  cattr_accessor :spatial_fields, :spatial_fields_indexed
31
31
  @@spatial_fields = []
32
32
  @@spatial_fields_indexed = []
@@ -51,6 +51,15 @@ module Mongoid
51
51
  index({name => '2d'}, options)
52
52
  end
53
53
 
54
+ def spatial_scope field, opts = {}
55
+ self.singleton_class.class_eval do
56
+ # define_method(:close) do |args|
57
+ define_method(:nearby) do |args|
58
+ queryable.where(field.near_sphere => args)
59
+ end
60
+ end
61
+ end
62
+
54
63
  end
55
64
 
56
65
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Geospatial
3
- VERSION = "2.3.0"
3
+ VERSION = "2.5.0"
4
4
  end
5
5
  end
data/spec/models/bar.rb CHANGED
@@ -8,4 +8,6 @@ class Bar
8
8
  has_one :rating, :as => :ratable
9
9
 
10
10
  spatial_index :location
11
+ spatial_scope :location
12
+
11
13
  end
@@ -3,9 +3,14 @@ require "spec_helper"
3
3
  describe Mongoid::Fields do
4
4
 
5
5
  context "spatial" do
6
+ before do
7
+ Bar.create_indexes
8
+ end
6
9
 
7
10
  it "should set some class methods" do
8
- Bar.near_location([1,1]).should eq([])
11
+ far = Bar.create!(name: "Far", location: [7,7])
12
+ near = Bar.create!(name: "Near", location: [2,2])
13
+ Bar.nearby([1,1]).should eq([near, far])
9
14
  end
10
15
 
11
16
  end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Geospatial::Box do
4
+
5
+ it "should work" do
6
+ alarm = Alarm.new(area: [[1,2], [3,4]])
7
+ alarm.area.should be_a Mongoid::Geospatial::Box
8
+ end
9
+
10
+
11
+ end
@@ -9,7 +9,14 @@ describe Mongoid::Geospatial::Point do
9
9
 
10
10
  it "should not fail if point is nil" do
11
11
  bar = Bar.create!(name: "Moe's")
12
- bar.location.x.should be_nil
12
+ bar.location.should be_nil
13
+ end
14
+
15
+ it "should set point to nil" do
16
+ bar = Bar.create!(name: "Moe's", location: [1, 1])
17
+ bar.location = nil
18
+ bar.location.should be_nil
19
+ bar.save.should be_true
13
20
  end
14
21
 
15
22
  describe "methods" do
@@ -36,6 +43,14 @@ describe Mongoid::Geospatial::Point do
36
43
  bar.location.radius_sphere[1].should be_within(0.0001).of(0.00015)
37
44
  end
38
45
 
46
+ it "should have a radius sphere helper in meters" do
47
+ bar.location.radius_sphere(1000, :m)[1].should be_within(0.0001).of(0.00015)
48
+ end
49
+
50
+ it "should have a radius sphere helper in miles" do
51
+ bar.location.radius_sphere(1, :mi)[1].should be_within(0.0001).of(0.00025)
52
+ end
53
+
39
54
  end
40
55
 
41
56
  describe "queryable" do
@@ -66,6 +81,15 @@ describe Mongoid::Geospatial::Point do
66
81
  Bar.where(:location.near => jim.location).should == [ paris, prague, berlin ]
67
82
  end
68
83
 
84
+ it "returns the documents sorted closest to furthest" do
85
+ Bar.near(location: jim.location).should == [ paris, prague, berlin ]
86
+ end
87
+
88
+ it "returns the documents sorted closest to furthest sphere" do
89
+ person = Person.new(:location => [ 41.23, 2.9 ])
90
+ Bar.near_sphere(location: jim.location).should == [ paris, prague, berlin ]
91
+ end
92
+
69
93
  it "returns the documents sorted closest to furthest sphere" do
70
94
  person = Person.new(:location => [ 41.23, 2.9 ])
71
95
  Bar.where(:location.near_sphere => jim.location).should == [ paris, prague, berlin ]
@@ -113,6 +137,11 @@ describe Mongoid::Geospatial::Point do
113
137
  it "returns the documents within a center_sphere" do
114
138
  Bar.where(:location.within_spherical_circle => [elvis.location, 0.5]).to_a.should include(mile9)
115
139
  end
140
+
141
+ it "returns the documents within a box" do
142
+ Bar.within_box(location: [elvis.location, elvis.location.map(&:ceil)]).to_a.should == [ mile3 ]
143
+ end
144
+
116
145
  end
117
146
 
118
147
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_geospatial
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-09-13 00:00:00.000000000 Z
13
+ date: 2012-09-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rgeo
@@ -181,6 +181,7 @@ files:
181
181
  - spec/models/river.rb
182
182
  - spec/mongoid_geospatial/extensions/core_ext_spec.rb
183
183
  - spec/mongoid_geospatial/field_option_spec.rb
184
+ - spec/mongoid_geospatial/fields/box_spec.rb
184
185
  - spec/mongoid_geospatial/fields/circle_spec.rb
185
186
  - spec/mongoid_geospatial/fields/line_spec.rb
186
187
  - spec/mongoid_geospatial/fields/point_spec.rb
@@ -227,6 +228,7 @@ test_files:
227
228
  - spec/models/river.rb
228
229
  - spec/mongoid_geospatial/extensions/core_ext_spec.rb
229
230
  - spec/mongoid_geospatial/field_option_spec.rb
231
+ - spec/mongoid_geospatial/fields/box_spec.rb
230
232
  - spec/mongoid_geospatial/fields/circle_spec.rb
231
233
  - spec/mongoid_geospatial/fields/line_spec.rb
232
234
  - spec/mongoid_geospatial/fields/point_spec.rb