2008-11-27 8 views
2

J'essaie d'utiliser le plugin GeoKit pour calculer la distance entre 2 points. Donc, l'idée est, je fais une recherche d'un article, et les résultats que je veux commander à distance. Donc j'ai un formulaire où j'entre l'article (que je cherche) et mon adresse. Ensuite, les rails doivent trouver tous les articles correspondant à ma requête et à ma commande par adresse.Rails JOIN TABLES

Alors maintenant, j'ai deux modèles: Article et utilisateur. Articles belongs_to Utilisateur et Utilisateur has_many Articles. Au modèle d'utilisateur j'ai l'information liée à ma latitude et longitude.

donc mon objet article a trois champs:

  • id
  • Nom
  • user_id (FK à modèle utilisateur)

Et mon modèle utilisateur a quatre champs

  • id
  • nom
  • latitude (latitude)
  • lng (longitude)

OK, d'avoir accès à l'information de l'utilisateur à travers des articles que je fais la requête:

@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") 

cela fonctionne. Mais quand je veux ajouter un: order => 'ASC distance' il échoue parce que l'ordre par requête utilise un champs Article.lat, et Article.lng pour calculer la distance, mais ces champs lat et lng, sont des membres de l'objet Utilisateur et pas membre de l'article.

BTW si je reçois la requête générée par les rails et je change la clause order by où utilise articles.lat/lng à users.lat/lng cela fonctionne.

Répondre

4

Je ne suis pas vraiment un expert SQL, et je trouve joint très dur pour envelopper ma tête (même plus que de déterminer multiples ne est comme if(!(foo != !bar & (!baz)))) mais je ne pense que ce soit la ligne :joins ou la ligne :include est redondante , ou même faux.

(je nettoyais votre requête pour que je puisse le comprendre, s'il vous plaît faire la même chose avec la question):

@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") 

Je suppose que soit le modèle de l'utilisateur et l'article doivent définir leur relation, de sorte que vous don Pas besoin d'une jointure manuelle ou que vous enlevez l'include.

Mais je ne vois pas dans ce code où la distance est réellement calculée (probablement un peu d'automagique dans GeoKit?). La distance doit être « nommé » avec le someting SQL comme:

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

Donc, vous pouvez vous référer à la distance de l'ordre par l'article, je ne pense pas que la base de données prend soin si le rubis objet ne contient la valeur. Peut-être que si vous nous avez montré le SQL généré, ce qui provoque des erreurs, et vous avez manipulé SQL, nous pourrions mieux comprendre ...

1

Je ne voulais pas mettre le SQL généré dans le premier post sinon ce serait trop chose :-)

j'utilisais simplement inclure, qui fonctionne, mais je ne sais pas pourquoi, inclure fait une jointure gauche , et j'ai besoin d'une jointure interne. Si je supprime l'inclure je ne peux pas accéder à l'information de l'utilisateur à travers l'objet article (comme par exemple les articles [0] .user.name)

ici c'est mon sql. si je change dans l'ordre par les champs articles.lat et articles.lng à users.lat et user.lng cela fonctionne:

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) 

Cordialement,

Victor