mongoid_geo 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.textile CHANGED
@@ -123,9 +123,9 @@ With the new @:geo@ option supplied by _mongoid-geo_ :
123
123
  Mongoid::Geo.spherical = true
124
124
  </pre>
125
125
 
126
- h2. News update (March 2)
126
+ h2. News update (May 9, 2011)
127
127
 
128
- * Added support for geoNear queries!!!
128
+ The geoNear queries can now convert the result into a Mongoid::Criteria, where distance from a given location is sorted in either descending or ascending (default) order
129
129
 
130
130
  <pre>
131
131
  class Address
@@ -145,18 +145,40 @@ class Position
145
145
  field :pos, :type => Array, :geo => true
146
146
  ...
147
147
  end
148
+ </pre>
149
+
150
+ Find all positions sorted nearest to the address loation
151
+ @nearest_positions = Position.geoNear(another_address.location, :pos)@
152
+
153
+ Perform distance locations in Speherical mode inside Mongo DB (default is :plane)
154
+ @nearest_positions = Position.geoNear(another_address.location, :pos, :mode => :sphere)@
155
+
156
+ Other options supported are: @:num, :maxDistance, :distanceMultiplier, :query@
157
+
158
+ GeoNear distance returns distance in degrees. Use distanceMultiplier to return in Miles or KM.
159
+
160
+ Set :distanceMultiplier to 6371 to get distance in KM
161
+ Set :distanceMultiplier to 3963.19 to get distance in Miles
162
+
163
+ You can also use the :unit option instead like this (supports :feet, :meters, :kms, :miles)
164
+
165
+ results = Address.geoNear @center.location, :location, :unit => :km
166
+
167
+ The query result is returned as an Array of Hashies
168
+
169
+ The result can be then converted to a Mongoid::Criteria if needed
170
+
171
+ pp results.as_criteria.to_a.map(&:distance)
172
+ pp results.as_criteria(:desc).to_a.map(&:distance)
173
+
174
+ Or converted to an array of Model instances
148
175
 
149
- # Find all positions sorted nearest to the address loation
150
- nearest_positions = Position.geoNear(another_address.location, :pos)
176
+ pp results.to_models.map(&:distance)
151
177
 
152
- # perform distance locations in Speherical mode inside Mongo DB (default is :plane)
153
- nearest_positions = Position.geoNear(another_address.location, :pos, :mode => :sphere)
178
+ Note that the :fromLocation field, stores the location the distance was last calculated as a hash of the Point it was calculated from
154
179
 
155
- # other options supported are: :num, :maxDistance, :distanceMultiplier, :query
180
+ @[23.5, -47].hash@
156
181
 
157
- # GeoNear distance returns distance in degrees. Use distanceMultiplier to return in Miles or KM.
158
- # set distanceMultiplier to 6371 to get distance in KM
159
- # set distanceMultiplier to 3963.19 to get distance in Miles
160
182
  </pre>
161
183
 
162
184
  If you need to operate on the Mongoid models referenced by the query result, simply call #to_models on it
@@ -26,6 +26,11 @@ module Mongoid #:nodoc
26
26
  end
27
27
 
28
28
  define_method("#{meth}=") do |value|
29
+ if options[:geo]
30
+ self.class.send :field, :distance, :type => Float
31
+ self.class.send :field, :fromLocation, :type => String
32
+ end
33
+
29
34
  if options[:type] == Array && options[:geo]
30
35
  value = case value
31
36
  when String
@@ -37,7 +42,7 @@ module Mongoid #:nodoc
37
42
  end
38
43
  value = value[0..1] if !value.nil?
39
44
  end
40
- value.reverse! if Mongoid::Geo.spherical && value
45
+ value.reverse! if Mongoid::Geo.spherical && value && !value.kind_of?(BSON::ObjectId)
41
46
  write_attribute(name, value)
42
47
  end
43
48
 
@@ -25,39 +25,38 @@ module Mongoid
25
25
  end
26
26
  end
27
27
 
28
- module Distance
29
- attr_reader :distance
30
-
31
- def set_distance dist
32
- @distance = dist
33
- end
34
- end
35
-
36
28
  module Model
37
29
  def to_model
38
30
  m = klass.where(:_id => _id).first.extend(Mongoid::Geo::Distance)
39
- m.set_distance distance
31
+ m.distance = distance
40
32
  m
41
33
  end
42
34
  end
43
35
 
44
36
  module Models
45
- def to_models
37
+ def to_models mode = nil
46
38
  distance_hash = Hash[ self.map {|item| [item._id, item.distance] } ]
39
+ from_hash = Hash[ self.map { |item| [item._id, item.fromLocation] } ]
47
40
 
48
41
  ret = to_criteria.to_a.map do |m|
49
- m.extend(Mongoid::Geo::Distance)
50
- m.set_distance distance_hash[m._id.to_s]
42
+ m.distance = distance_hash[m._id.to_s]
43
+ m.fromLocation = from_hash[m._id.to_s]
44
+ m.save if mode == :save
51
45
  m
52
46
  end
53
-
54
47
  ret.sort {|a,b| a.distance <=> b.distance}
55
48
  end
49
+
50
+ def as_criteria direction = :asc
51
+ to_models(:save)
52
+ ids = first.klass.where().map(&:_id)
53
+ Mongoid::Criteria.new(first.klass).where(:_id.in => ids, :fromLocation => first.fromLocation).send(direction, :distance)
54
+ end
56
55
 
57
56
  def to_criteria
58
- ids = map(&:_id)
59
- first.klass.where(:_id.in => ids)
60
- end
57
+ ids = map(&:_id)
58
+ Mongoid::Criteria.new(first.klass).where(:_id.in => ids).desc(:distance)
59
+ end
61
60
  end
62
61
 
63
62
  module Near
@@ -97,6 +96,7 @@ module Mongoid
97
96
  # Calculate distance in KM or Miles if mongodb < 1.7
98
97
  r[distance_meth] ||= calc_distance(r, center, location_attribute, options) if Mongoid::Geo.mongo_db_version < 1.7
99
98
  r['klass'] = klass
99
+ r['from'] = center.hash
100
100
  end
101
101
  query_result
102
102
  end
@@ -105,10 +105,11 @@ module Mongoid
105
105
  qres.map do |qr|
106
106
  res = Hashie::Mash.new(qr['obj'].to_hash).extend(Mongoid::Geo::Model)
107
107
  res.klass = qr['klass']
108
+ res.fromLocation = qr['from']
108
109
  res.distance = qr[distance_meth]
109
110
  res._id = qr['obj']['_id'].to_s
110
111
  res
111
- end
112
+ end
112
113
  end
113
114
 
114
115
  private
@@ -116,39 +117,8 @@ module Mongoid
116
117
  def distance_multiplier options
117
118
  distanceMultiplier = options[:distanceMultiplier]
118
119
  return distanceMultiplier if distanceMultiplier && Mongoid::Geo.mongo_db_version >= 1.7
119
-
120
- return radian_multiplier[options[:unit]] if options[:unit] && Mongoid::Geo.mongo_db_version >= 1.7
121
- unit_multiplier[options[:unit]] if options[:unit]
122
- end
123
-
124
- def unit_multiplier
125
- {
126
- :feet => 0.305,
127
- :ft => 0.305,
128
- :m => 1,
129
- :meters => 1,
130
- :meter => 1,
131
- :km => 6371,
132
- :kms => 6371,
133
- :mil => 3959,
134
- :mile => 3959,
135
- :miles => 3959
136
- }
137
- end
138
-
139
- def radian_multiplier
140
- {
141
- :feet => 364491.8,
142
- :ft => 364491.8,
143
- :m => 111170,
144
- :meter => 111170,
145
- :meters => 111170,
146
- :km => 111.17,
147
- :kms => 111.17,
148
- :mil => 69.407,
149
- :mile => 69.407,
150
- :miles => 69.407
151
- }
120
+ return Mongoid::Geo::Unit.distMultiplier(options[:unit]) if options[:unit]
121
+ 1
152
122
  end
153
123
 
154
124
  def query_results klass, query
@@ -0,0 +1,83 @@
1
+ module Mongoid
2
+ module Geo
3
+ class Unit
4
+ class << self
5
+ def key unit = :km
6
+ unit = unit.to_sym
7
+ methods.grep(/_unit/).each do |meth|
8
+ return meth.to_s.chomp('_unit').to_sym if send(meth).include? unit
9
+ end
10
+ raise ArgumentError, "Unknown unit key: #{unit}"
11
+ end
12
+
13
+ def distMultiplier unit = :km
14
+ unit_key = key(unit)
15
+ return radian_multiplier[unit_key] if unit_key && Mongoid::Geo.mongo_db_version >= 1.7
16
+ unit_multiplier[unit_key] if unit_key
17
+ end
18
+
19
+ def precision
20
+ {
21
+ :feet => 0,
22
+ :meters => 2,
23
+ :kms => 4,
24
+ :miles => 4,
25
+ :radians => 4
26
+ }
27
+ end
28
+
29
+ # from mongoid-geo, as suggested by niedhui :)
30
+ def radian_multiplier
31
+ {
32
+ :feet => 364491.8,
33
+ :meters => 111170,
34
+ :kms => 111.17,
35
+ :miles => 69.407,
36
+ :radians => 1
37
+ }
38
+ end
39
+
40
+ def unit_multiplier
41
+ {
42
+ :feet => 0.305,
43
+ :meters => 1,
44
+ :kms => 6371,
45
+ :miles => 3959
46
+ }
47
+ end
48
+
49
+ def meters_map
50
+ {
51
+ :feet => 3.2808,
52
+ :meters => 1,
53
+ :kms => 0.001,
54
+ :miles => 0.00062137,
55
+ :radians => 111170
56
+ }
57
+ end
58
+
59
+ protected
60
+
61
+ def feet_unit
62
+ [:ft, :feet, :foot]
63
+ end
64
+
65
+ def meters_unit
66
+ [:m, :meter, :meters]
67
+ end
68
+
69
+ def kms_unit
70
+ [:km, :kms, :kilometer, :kilometers]
71
+ end
72
+
73
+ def miles_unit
74
+ [:mil, :mile, :miles]
75
+ end
76
+
77
+ def radians_unit
78
+ [:rad, :radians]
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
data/lib/mongoid/geo.rb CHANGED
@@ -4,6 +4,7 @@ module Mongoid
4
4
  end
5
5
 
6
6
  require 'mongoid/geo/point'
7
+ require 'mongoid/geo/unit'
7
8
  require 'mongoid/geo/fields'
8
9
  require 'mongoid/geo/criteria'
9
10
  require 'mongoid/geo/index'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_geo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-04 00:00:00.000000000Z
12
+ date: 2011-05-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2152917100 !ruby/object:Gem::Requirement
16
+ requirement: &2152937900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2.4'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2152917100
24
+ version_requirements: *2152937900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mongoid
27
- requirement: &2152916640 !ruby/object:Gem::Requirement
27
+ requirement: &2152965320 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.0.1
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2152916640
35
+ version_requirements: *2152965320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bson
38
- requirement: &2152916180 !ruby/object:Gem::Requirement
38
+ requirement: &2152964860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '1.3'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2152916180
46
+ version_requirements: *2152964860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activesupport
49
- requirement: &2152915720 !ruby/object:Gem::Requirement
49
+ requirement: &2152964400 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 3.0.4
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2152915720
57
+ version_requirements: *2152964400
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: hashie
60
- requirement: &2152931640 !ruby/object:Gem::Requirement
60
+ requirement: &2152963940 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: 0.4.0
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *2152931640
68
+ version_requirements: *2152963940
69
69
  description: Geo spatial extension on Mongoid 2, to add more geo-spatial capabilities
70
70
  email:
71
71
  - kmandrup@gmail.com
@@ -85,6 +85,7 @@ files:
85
85
  - lib/mongoid/geo/index.rb
86
86
  - lib/mongoid/geo/inflections.rb
87
87
  - lib/mongoid/geo/point.rb
88
+ - lib/mongoid/geo/unit.rb
88
89
  - lib/mongoid/geo.rb
89
90
  - lib/mongoid_geo.rb
90
91
  - MIT-LICENSE
@@ -110,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
111
  version: 1.3.6
111
112
  requirements: []
112
113
  rubyforge_project:
113
- rubygems_version: 1.7.2
114
+ rubygems_version: 1.8.0
114
115
  signing_key:
115
116
  specification_version: 3
116
117
  summary: Adds extra convenience methods for geo-spatial operations etc.