컨트롤러 메소드에 있던 Ruby 코드를 최적화하여 직접적인 데이터베이스 쿼리로 대체했습니다. 교체가 제대로 작동하고 훨씬 빨라졌습니다. 문제는 Rails가 올바른 쿼리를 찾아 낼 수 있었는지 전혀 모르겠습니다.레일즈 쿼리는 어떻게 작동합니까?
위 쿼리의 목적은 지정된 위도와 경도의 특정 거리 내에있는 장소 모델의 태그 수를 계산하는 것입니다. 거리 부분은 GeoKit 플러그인 (기본적으로 선택 항목에 적절한 삼각법 계산을 추가하는 편리한 방법을 추가 함)으로 처리되며 태그 지정 부분은 다형 연관을 사용하는 acts_as_taggable_on_steroids 플러그인으로 수행됩니다. MyTag 클래스는이 구현
places = Place.find(:all, :origin=>latlng, :order=>'distance asc', :within=>distance, :limit=>200)
tag_counts = MyTag.tagcounts(places)
deep_tag_counts=Array.new()
tag_counts.each do |tag|
count=Place.find_tagged_with(tag.name,:origin=>latlng, :order=>'distance asc', :within=>distance, :limit=>200).size
deep_tag_counts<<{:name=>tag.name,:count=>count}
end
: 아래
은 원래의 코드def MyTag.tagcounts(places)
alltags = places.collect {|p| p.tags}.flatten.sort_by(&:name)
lasttag=nil;
tagcount=0;
result=Array.new
alltags.each do |tag|
unless (lasttag==nil || lasttag.name==tag.name)
result << MyTag.new(lasttag,tagcount)
tagcount=0
end
tagcount=tagcount+1
lasttag=tag
end
unless lasttag==nil then
result << MyTag.new(lasttag,tagcount)
end
result
end
내가 원래 어려운 가지고 올 발견이 내 (매우 추한) 첫 번째 시도였다 SQL에서이 작업을 수행하려면 오른쪽 레일 명령을 사용해야합니다.
deep_tag_counts=Place.find(:all,:select=>'name,count(*) as count',:origin=>latlng,:within=>distance,:joins=>:tags, :group=>:tag_id)
이 같은 SQL 쿼리 결과 : 새로운 대체이 하나의 라인 내부와 :
SELECT name,count(*) as count, (ACOS(least(1,COS(0.897378837271255)*COS(-0.0153398733287034)*COS(RADIANS(places.lat))*COS(RADIANS(places.lng))+
COS(0.897378837271255)*SIN(-0.0153398733287034)*COS(RADIANS(places.lat))*SIN(RADIANS(places.lng))+
SIN(0.897378837271255)*SIN(RADIANS(places.lat))))*3963.19)
AS distance FROM `places` INNER JOIN `taggings` ON (`places`.`id` = `taggings`.`taggable_id` AND `taggings`.`taggable_type` = 'Place') INNER JOIN `tags` ON (`tags`.`id` = `taggings`.`tag_id`) WHERE (places.lat>50.693170735732 AND places.lat<52.1388692642679 AND places.lng>-2.03785525810908 AND places.lng<0.280035258109084 AND (ACOS(least(1,COS(0.897378837271255)*COS(-0.0153398733287034)*COS(RADIANS(places.lat))*COS(RADIANS(places.lng))+
COS(0.897378837271255)*SIN(-0.0153398733287034)*COS(RADIANS(places.lat))*SIN(RADIANS(places.lng))+
SIN(0.897378837271255)*SIN(RADIANS(places.lat))))*3963.19)
<= 50) GROUP BY tag_id
GeoKit에서 인 삼각를 (무시하고 결과 근원 매개 변수) 내가 이것에 대해 알 수없는 것은 Rails가 '태그'에 가입하라는 명령에서 알아낼 수 있었고, JOIN에 '태그 지정'을 포함해야한다는 것입니다. 장소와 태그 테이블을 결합하는 직접적인 방법), 또한 다형성 (polymorphic)의 것들을 사용해야만했습니다. 즉
은 도대체 그것을 어떻게 (제대로)이 비트 마련 :
INNER JOIN `taggings` ON (`places`.`id` = `taggings`.`taggable_id` AND `taggings`.`taggable_type` = 'Place') INNER JOIN `tags` ON (`tags`.`id` = `taggings`.`tag_id`)
... 나는 코드에서 taggings 테이블을 언급 한 적이 주어진! 여기에 후드 아래에가는 마법에 대한 통찰력을 줄 수
class Tag < ActiveRecord::Base
has_many :taggings, :dependent=>:destroy
...
end
누구나 다음 taggable 플러그인에 파고, 레일이있는 유일한 단서는이 것 같다?