0

我正在尝试根据我的数据库结构创建一个 json 数组(实际上是字符串)。我有以下关系:

Country > State > City

我现在这样做的方式非常低效(N + 1):

data = "[" + Country.all.map{ |country|
  {
    name: country.name,
    states: country.states_data
  }.to_json
}.join(",") + "]"

然后在国家模型上:

def states_data
  ret_states = []
  states.all.each do |state|
    ret_states.push name: state.name, cities: state.cities_data
  end
  ret_states
end

然后在状态模型上:

def cities_data
  ret_cities = []
  cities.all.each do |city|
    ret_cities.push name: city.name, population: city.population
  end
  ret_cities
end

我怎样才能更有效地做到这一点?

4

2 回答 2

1

渴望加载州和城市。请小心,因为这可能会占用大型数据集的大量内存。请参阅此处的文档http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations。只要有可能,我喜欢使用除了包含之外的连接来一次获取所有数据。

#to_json 还将为您序列化数组,因此您无需手动添加 JSON 位。

您上面的代码可以像这样更改:

data = Country.joins(:states => :cities).includes(:states => :cities).all.map{ |country|
  {
    name: country.name,
    states: country.states_data
  }
}.to_json

但是您也可以消除对 _data 方法的需求。

data = Country.joins(:states => :cities).includes(:states => :cities).to_json(
  :only => :name,
  :include => {
    :states => {
      :only => :name,
      :include => {
        :cities => {
          :only => [:name, :population]
        }
      }
    }
  }
)

这很丑陋,因此您可能需要考虑为每个模型覆盖#as_json。网上有很多关于这方面的信息。

于 2013-07-09T22:02:18.787 回答
1

您可以提供转换为 json 时要包含的模型。

country.to_json(:include => {:states => {:include => :cities}})

检查http://apidock.com/rails/ActiveRecord/Serialization/to_json _

于 2013-07-09T18:16:30.103 回答