2010-06-04 14 views
0

J'utilise will_paginate pour paginer mes résultats de recherche geokit. Le code fonctionne, cependant, quand on regarde le journal, il fait le double de la requête Geokit lorsque vous utilisez l'appel will_paginate suivant:Will_paginate et geokit misbehavior (double requête)

@posts = Post.paginate :page => params[:page], :per_page => 1, 
         :origin => @search, :within => @miles, :include => :user 

Ceci est l'appel initial non paginé qui fonctionne comme prévu (une seule requête):

@posts = Post.find(:all, :origin => @search, :within => @miles, :include => :user) 

Ce qui suit est la sortie du journal lors de l'utilisation du premier appel will_paginate:

Processing PostsController#search (for 127.0.0.1 at 2010-06-03 22:10:29) [POST] 
    Parameters: {"commit"=>"Search", "action"=>"search", "authenticity_token"=>"K9Btfu6p7pz2mt+lWH0Fx0O7qj+0QY21JpfgyWT738I=", "controller"=>"posts", "location"=>"new york"} 
Google geocoding. Address: new york. Result: <?xml version="1.0" encoding="UTF-8" ?> 
<kml xmlns="http://earth.google.com/kml/2.0"><Response> 
    <name>new york</name> 
    <Status> 
    <code>200</code> 
    <request>geocode</request> 
    </Status> 
    <Placemark id="p1"> 
    <address>New York, NY, USA</address> 
    <AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>NY</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>New York</SubAdministrativeAreaName><Locality><LocalityName>New York</LocalityName></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails> 
    <ExtendedData> 
     <LatLonBox north="40.8494506" south="40.5788125" east="-73.7498541" west="-74.2620917" /> 
    </ExtendedData> 
    <Point><coordinates>-74.0059729,40.7142691,0</coordinates></Point> 
    </Placemark> 
</Response></kml> 
    Post Load (0.7ms) SELECT *, 
(ACOS(least(1,COS(0.710598048337988)*COS(-1.2916478932467)*COS(RADIANS(posts.lat))*COS(RADIANS(posts.lng))+ 
COS(0.710598048337988)*SIN(-1.2916478932467)*COS(RADIANS(posts.lat))*SIN(RADIANS(posts.lng))+ 
SIN(0.710598048337988)*SIN(RADIANS(posts.lat))))*3963.19) 
AS distance FROM `posts` WHERE (((posts.lat>40.352844467866 AND posts.lat<41.075693732134 AND posts.lng>-74.4827993840952 AND posts.lng<-73.5291464159048)) AND (
(ACOS(least(1,COS(0.710598048337988)*COS(-1.2916478932467)*COS(RADIANS(posts.lat))*COS(RADIANS(posts.lng))+ 
COS(0.710598048337988)*SIN(-1.2916478932467)*COS(RADIANS(posts.lat))*SIN(RADIANS(posts.lng))+ 
SIN(0.710598048337988)*SIN(RADIANS(posts.lat))))*3963.19) 
<= 25)) LIMIT 0, 1 
    Post Columns (2.4ms) SHOW FIELDS FROM `posts` 
    User Columns (2.2ms) SHOW FIELDS FROM `users` 
    User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 1) 
Google geocoding. Address: new york. Result: <?xml version="1.0" encoding="UTF-8" ?> 
<kml xmlns="http://earth.google.com/kml/2.0"><Response> 
    <name>new york</name> 
    <Status> 
    <code>200</code> 
    <request>geocode</request> 
    </Status> 
    <Placemark id="p1"> 
    <address>New York, NY, USA</address> 
    <AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>NY</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>New York</SubAdministrativeAreaName><Locality><LocalityName>New York</LocalityName></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails> 
    <ExtendedData> 
     <LatLonBox north="40.8494506" south="40.5788125" east="-73.7498541" west="-74.2620917" /> 
    </ExtendedData> 
    <Point><coordinates>-74.0059729,40.7142691,0</coordinates></Point> 
    </Placemark> 
</Response></kml> 
    SQL (0.4ms) SELECT count(*) AS count_all FROM `posts` WHERE (((posts.lat>40.352844467866 AND posts.lat<41.075693732134 AND posts.lng>-74.4827993840952 AND posts.lng<-73.5291464159048)) AND (
(ACOS(least(1,COS(0.710598048337988)*COS(-1.2916478932467)*COS(RADIANS(posts.lat))*COS(RADIANS(posts.lng))+ 
COS(0.710598048337988)*SIN(-1.2916478932467)*COS(RADIANS(posts.lat))*SIN(RADIANS(posts.lng))+ 
SIN(0.710598048337988)*SIN(RADIANS(posts.lat))))*3963.19) 
<= 25)) 
Rendering template within layouts/application 

Comme vous pouvez le voir le KML/XML et les requêtes SQL sont doublées. Une idée de ce qui se passe et comment je peux le réparer? Merci!

-Tony

Répondre

0

En fait, ce comportement est standard. will_paginate compte d'abord le nombre d'enregistrements, puis récupère 20 lignes, en fonction de la page visible et du nombre de lignes sur la page (donc les requêtes ne sont pas complètement identiques).

Le nombre est nécessaire pour afficher le nombre de pages.

Mais votre journalisation n'a pas vraiment de sens pour moi, car la requête will_paginate limiterait le nombre à 20 (ou toute taille de page), les requêtes affichées ne sont pas entièrement identiques: je vois des conditions différentes par exemple.

+0

Merci pour la clarification! Ça a du sens. Y a-t-il un moyen de mettre en cache les résultats? J'ai deux peurs avec ceci: 1. Limites d'API de Google/Yahoo et 2. Combien de temps cela prend pour produire l'appel d'API de Google + requête de SQL. Sur ma machine locale, cela prend environ 200 + ms pour terminer sur une seule requête - quand will_paginate est utilisé, il va de 300-430 + ms. Des pensées? – slythic

+0

200ms semble beaucoup. Avez-vous des index définis sur vos colonnes lat/lng? En outre, la recherche sur les boîtes de délimitation pourrait améliorer les performances que je présume (semble plus facile). Plus de détails ici: http://geokit.rubyforge.org/readme.html, mais je suppose que vous l'auriez lu aussi. Rails met en cache automatiquement les requêtes identiques, mais ces requêtes ne le sont jamais. – nathanvda