コントローラメソッドにあったいくつかのRubyコードを最適化し、直接データベースクエリに置き換えました。交換が正常に動作しているように見え、はるかに高速です。それは、Railsがどのように正しいクエリを使い分けることができたか分かりません。このレールクエリはどのように地球上で動作していますか?
クエリの目的は、指定された緯度と経度から特定の距離内にあるPlaceモデルのタグ数を計算することです。距離部分は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に「タグ付け」を含める必要があったかということです。場所やタグのテーブルに参加する直接的な方法)、多態的なものを使用しなければならないということです。いったいそれをどうやったのかつまり
、(正しく)このビットを思い付く:
INNER JOIN `taggings` ON (`places`.`id` = `taggings`.`taggable_id` AND `taggings`.`taggable_type` = 'Place') INNER JOIN `tags` ON (`tags`.`id` = `taggings`.`tag_id`)
...私はコード内のタギング表を述べたことがないことを考えます!ここではフードの下で起こって魔法のいくつかの洞察を与えることができる
class Tag < ActiveRecord::Base
has_many :taggings, :dependent=>:destroy
...
end
誰:タグ付けできるプラグインに掘り、Railsが持っている唯一の手掛かりはこれのようですか?