Rails JOIN TABLES

时间:2008-11-27 14:57:47

标签: ruby-on-rails

我正在尝试使用GeoKit插件来计算2点之间的距离。所以我的想法是,我搜索一篇文章,我希望按距离排序。所以我有一个表格,我输入文章(我正在寻找)和我的地址。然后rails必须找到与我的查询匹配的所有文章,并按地址排序。

所以现在,我有两个模型:文章和用户。文章belongs_to用户和用户has_many文章。在用户模型中,我有与纬度和经度相关的信息。

所以我的文章对象有三个字段:

  • ID
  • 名称
  • user_id(FK到用户模型)

我的用户模型有四个字段

  • ID
  • 名称
  • lat(纬度)
  • lng(经度)

好的,要通过我执行查询的文章访问用户信息:

@articles = Article.find(:all,:conditions=>"vectors @@ to_tsquery('büch')",:joins=>" INNER JOIN users ON users.id = articles.user_id",:include=>:user,:origin=>"Augustusplatz,8,leipzig,germany")

它有效。但是当我想添加:order =>'距离ASC'时它会失败,因为查询的顺序是使用Article.lat和Article.lng字段来计算距离,但这些字段是lat和lng,是User对象的成员而不是文章成员。

顺便说一句,如果我得到rails生成的查询,并且我更改了order by子句,其中使用articles.lat/lng到users.lat/lng它可以工作。

2 个答案:

答案 0 :(得分:4)

我不是一个真正的SQL专家,而且我发现很难加入我的脑袋(甚至比找出if(!(foo != !bar & (!baz)))之类的多个NOT更多但是我确实觉得:joins行或:include行是多余的,甚至是错误的。

(我清理了你的查询,所以我能理解它,请对问题做同样的事情):

@articles = Article.find(:all,
    :conditions=>"vectors @@ to_tsquery('büch')",
    :joins=>" INNER JOIN users ON users.id = articles.user_id",
    :include=>:user,
    :origin=>"Augustusplatz,8,leipzig,germany")

我想用户和文章的模型应该定义它们的关系,因此您不需要手动连接或删除包含。

但是我没有从这段代码中看到实际计算距离(GeoKit可能有些自动化?)。距离应该用SQL命名为“命名”,如:

SELECT (some_heavy_calculation(user.lat, user.long)) AS distance, ... ;

所以你可以在order by子句中引用距离,我认为数据库不关心 ruby​​ 对象是否包含该值。

也许如果你向我们展示了生成的SQL,这会导致错误,而你操纵SQL我们可以更好地理解......

答案 1 :(得分:1)

我不想把第一篇文章中生成的sql,否则会有太多的事情: - )

我使用的只是包含,有效,但我不知道为什么,包括左连接,我需要一个内连接。如果我删除了包含我无法通过文章对象访问用户信息(例如文章[0] .user.name)

这是我的sql。如果我通过字段articles.lat和articles.lng更改订单到users.lat和user.lng它的工作原理:

SELECT "articles"."id" AS t0_r0, "articles"."name" AS t0_r1, "articles"."price" AS t0_r2, "articles"."user_id" AS t0_r3, "articles"."created_at" AS t0_r4, "articles"."updated_at" AS t0_r5, "articles"."vectors" AS t0_r6, "users_articles"."id" AS t1_r0, "users_articles"."name" AS t1_r1, "users_articles"."address" AS t1_r2, "users_articles"."created_at" AS t1_r3, "users_articles"."updated_at" AS t1_r4, "users_articles"."lat" AS t1_r5, "users_articles"."lng" AS t1_r6, "users_articles"."zipcode" AS t1_r7 FROM "articles"  LEFT OUTER JOIN "users" users_articles ON "users_articles".id = "articles".user_id     INNER JOIN users ON users.id = articles.user_id WHERE (vectors @@ to_tsquery('büch'))  ORDER BY                   (ACOS(least(1,COS(0.896021391737553)*COS(0.216084610510851)*COS(RADIANS(articles.lat))*COS(RADIANS(articles.lng))+
              COS(0.896021391737553)*SIN(0.216084610510851)*COS(RADIANS(articles.lat))*SIN(RADIANS(articles.lng))+
              SIN(0.896021391737553)*SIN(RADIANS(articles.lat))))*3963.19)

此致

维克多