2008-11-27 2 views
2

Я пытаюсь использовать плагин GeoKit для вычисления расстояния между двумя точками. Итак, идея в том, что я ищу статью, и результаты, которые я хочу заказать по расстоянию. Поэтому у меня есть форма, в которой я ввожу статью (которую я ищу) и мой адрес. Затем рельсы должны найти все статьи, соответствующие моему запросу и порядку по адресу.Rails JOIN TABLES

Итак, у меня есть две модели: статья и пользователь. Статьи принадлежат пользователю и пользователю has_many. В модели User у меня есть информация, связанная с моей широтой и долготой.

Так моя статья объект имеет три поля:

  • ID
  • имя
  • user_id (FK в модели пользователя)

И моя модель пользователя имеет четыре поля

  • ID
  • имя
  • лат (широта)
  • LNG (долгота)

OK, чтобы иметь доступ к информации пользователя через статей я сделать запрос:

@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 => 'distance ASC', он терпит неудачу, потому что порядок по запросу использует поля Article.lat и Article.lng для вычисления расстояния, но эти поля lat и lng являются членами объекта пользователя и не член статьи.

BTW, если я получаю запрос, сгенерированный рельсами, и я изменяю порядок order by, где использует articles.lat/lng для users.lat/lng, он работает.

ответ

4

Я на самом деле не эксперт SQL, и я считаю, присоединяется очень трудно обернуть вокруг головы (даже больше, чем выяснить несколько НЕ как if(!(foo != !bar & (!baz)))), но я чувствую, что либо :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") 

Я думаю, либо модель пользователя и статьи следует определить их отношения, так что вы дон Не нужно ручное соединение или что вы удалите include.

Но я не вижу из этого кода, где фактически вычисляется расстояние (возможно, какое-то автоматическое в GeoKit?). Расстояние должно быть «под названием» с SQL: как коснуться

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

Таким образом, вы можете обратиться на расстояние в порядке п, я не думаю, что заботится база данных, если рубин объект не введите значение.

Возможно, если вы показали нам сгенерированный SQL, который вызывает ошибки, и вы манипулировали SQL, мы могли бы понять лучше ...

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) 

С уважением,

Виктор