2017-03-24 78 views
2

我有一個車站模型,可以有多個設備,而每個設備屬於一個車站。每個站都有一個地址,這是一個多態模型:如何通過has_one關聯的屬性對模型進行分組和計數?

/app/models/station.rb

class Station < ApplicationRecord 
    has_one :address, as: :addressable, dependent: :destroy 
    has_many :devices 
end 

/app/models/device.rb

class Device < ApplicationRecord 
    belongs_to :station 
    has_one :address, through: :station 
end 

/應用/型號/address.rb

# @attr [String] city City name of address 
class Address < ApplicationRecord 
    belongs_to :addressable, polymorphic: true 
end 

現在我需要兩組數據對我的圖表:

  • 由城市數量的站
  • 由城市數量的設備

什麼工作是由城市越來越站數:

def stations_by_city 
    # collect data 
    tmp_result = Address.where(addressable_type: 'Station').group(:city).count 
    # sort and return top five cities 
    result = Hash[tmp_result.sort_by { |_k, v| -v }[0..4]] 
    # result = {"City-1"=>17, "City-2"=>14, "City-3"=>14, "City-4"=>12, "City-5=>11} 
end 

做同樣由城市ISN設備」沒有按預期工作。現在我這樣做:

def devices_by_city 
    stations = Station.all.includes(:address) 
    tmp_result = {} 
    # for each unique city 
    list_of_cities.uniq.each do |city| 
    number_of_devices = 0 
    # check all stations 
    stations.each do |station|   
    address = station.address 
    # check if station is in city 
    if address.city == city 
     # and add to counter 
     number_of_devices += station.devices.count 
    end 
    end 
    # append to resulting hash 
    tmp_result[city] = number_of_devices 
    end 
    result = Hash[tmp_result.sort_by { |_k, v| -v }[0..4]] 
end 

def list_of_cities 
    cities = [] 
    stations = Station.all.includes(:address) 
    stations.each do |station| 
    address = station.address 
    cities << address.city 
    end 
    cities 
    end 
end 

我有重複的數據庫查找,它通常很難看。我怎樣才能以更好的方式編寫這個查詢?嘗試過各種[.joins,.where,.group]組合,但其中沒有一個可以工作。添加through: :station到設備模型幫助在其他地方卻沒有簡化我的問題......從答案

# start join from station model 
tmp_result = Station.joins(:address, :devices).group(:city).count 

# start join from device model 
tmp_result = Device.joins(station: :address).group(:city).count 

更新起價設備型號連接是最快的國家之一:

Timing for old query 
    0.530000 0.050000 0.580000 ( 0.668664) 
Timing for query starting from station model 
    0.020000 0.000000 0.020000 ( 0.024881) 
Timing for query starting from device model 
    0.010000 0.000000 0.010000 ( 0.009616) 

回答

0

你可以joins之間Station,AddressDevice模型和group_by res在城市,然後運用ULTS count

def devices_by_city_updated 
    temp_result = Station.joins(:address, :devices).group(:city).count 
    result = Hash[tmp_result.sort_by { |_k, v| -v }[0..4]] 
end 

這個查詢會做一個單一的數據庫查詢來獲取所有的信息。

您也可以從Device模型開始加入。但是,你必須參加嵌套協會對於這項工作:

def self.devices_by_city_another 
    tmp_result = Device.joins(station: :address).group(:city).count 
    result = Hash[tmp_result.sort_by { |_k, v| -v }[0..4]] 
end 

可以在the docs

+0

工程檢查的詳細信息。由於這是連接鏈接,我必須開始與站的這個加入。我以某種方式開始與地址或設備,因爲我正在尋找...設備;-) –

+0

@MarkTowd我更新了答案,以顯示如何從「設備」模型開始:) – Aegis

+0

再次感謝,它甚至更快.. 。 –

相關問題