我的Rails应用程序中有这两个模型:
create_table "projects", force: :cascade do |t|
...
t.float "latitude", limit: 24, default: 0.0
t.float "longitude", limit: 24, default: 0.0
用户:
create_table "users", force: :cascade do |t|
...
t.float "last_latitude", limit: 24, default: 0.0
t.float "last_longitude", limit: 24, default: 0.0111
我有一个自定义类:
class CalculusAid
public
# point_one and point_two are arrays of [latitude, longitude]
def self.distance point_one, point_two
first_point_latitude, first_point_longitude = point_one
second_point_latitude, second_point_longitude = point_two
latitude_difference_in_radians = (first_point_latitude - second_point_latitude).to_radians
longitude_difference_in_radians = (first_point_longitude - second_point_longitude).to_radians
#Math stuff
a = Math.sin(latitude_difference_in_radians/2) * Math.sin(latitude_difference_in_radians/2) +
Math.cos(first_point_latitude.to_radians) * Math.cos(second_point_latitude.to_radians) *
Math.sin(longitude_difference_in_radians/2) * Math.sin(longitude_difference_in_radians/2);
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
distance_in_kilometers = 6371 * c; # Multiply by 6371 to get Kilometers
return distance_in_kilometers
end
...
我不想做的是从用户那里返回0到50公里之间的5个随机项目,我想用这样的方法做到这一点
class User < ActiveRecord::Base
def get_nearby_projects
@nearby_projects = User.joins(:projects).where(CalculusAid.distance([self.last_longitude],self.last_latitude][project.longitude,project.latitude]) < 50).limit(5).order("RAND()")
end
但我不知道我是否可以在where语句中使用自定义方法,或者语法是否正确。
答案 0 :(得分:1)
这是不可能直接的,因为Rails只构建一个由MySQL执行的查询,并从DB服务器获取结果。这是一个原子操作,无法将lambda传递给MySQL来过滤结果。
但MySQL有built-in math functions:
@nearby_projects = ActiveRecord::Base.connection.execute <<-SQL
SELECT *
FROM users
JOIN projects ON (???) -- unclear from the code you’ve pasted
WHERE
50 > 6371 * (SIN(users.last_latitude + .......
SQL
希望它有所帮助。
答案 1 :(得分:-1)
为什么不是一个简单的“范围<50km”。 另外,你可以在Order语句中调用random吗?
SELECT a,b,c, ...
FROM table
WHERE range < 50
ORDER BY RAND()
LIMIT 5;