我可以在WHERE语句中使用Custom方法吗?

时间:2015-09-03 09:02:53

标签: mysql sql ruby-on-rails ruby activerecord

我的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语句中使用自定义方法,或者语法是否正确。

2 个答案:

答案 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;