采用多个连接表

时间:2018-04-18 13:35:03

标签: ruby-on-rails ruby postgresql activerecord

我有这个数据模型

House has_many :floors(attributes => name,size,city)
楼层has_many :rooms, belongs_to :house(attributes => name,rooms_count)
会议室has_many :furnitures, belongs_to :floor(属性=>名称,大小)
家具belongs_to :room(属性=>名称,大小,颜色)

我希望以这种方式查询

House.where(city: 'Paris').joins(floors: {rooms: :furnitures}).pluck(name, floors.id, floors.name, rooms.name, furnitures.name)

这是我想要的SQL请求:

=> SELECT houses.name, floors.id, floors.name, rooms.id, rooms.name, furnitures.id, furnitures.name FROM "houses" INNER JOIN "floors" ON "floors"."company_id" = "houses"."id" INNER JOIN "rooms" ON "rooms"."building_id" = "floors"."id" INNER JOIN "furnitures" ON "furnitures"."floor_id" = "rooms"."id" WHERE "houses"."name" = $1 [["city", "Paris"]]

现在我在一大堆数组中得到了原始数据,我想这样排序,但我很困惑:

[ { name: 'toto', floors: [ { id: '123', name: 'tata' rooms: [ { name: 'titi', furnitures: [ { name: 'table' }, { name: 'chair' } ] } ] } ] } ] 我需要避免N + 1请求,只拒绝选择*。 pluck_to_hash gem可能会有所帮助,但对多表查询不起作用。 谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

正如你所说,你可以把你想要的结果作为一个带有pluck的数组

function reverseFunc(str) {
    var a = "" , c;
    var b = 0;
    for(var i = str.length-1; i >=0; i--)
        {
            c = str.charAt(i);

            if((str[i] != ' ' && str[i] != '\n' && str[i] != '\t') || b > 0)
            {
                a = c + a;
                b++;
            }
        }
    return a;
}

为了给他们一个哈希,我认为你需要手动进行分组。如下所示。

arrays = House.where(city: 'Paris').joins(floors: {rooms: :furnitures}).pluck('name', 'floors.id', 'floors.name', 'rooms.name', 'furnitures.name')

会得到类似

的东西
arrays = [
  ['toto', 123, 'tata', 'titi', 'table'], 
  ['toto', 123, 'tata', 'titi', 'chair'],
  ['bob', 124, 'sue', 'hall', 'table'],
  ['bob', 124, 'sue', 'foyer', 'table']
]

arrays.inject([]) do |results, row|
  name, floor_id, floor_name, room_name, furniture_name = row

  house = results.detect{|o| o[:name] == name} || {name: name, floors: []}
  results |= [house]

  floor = house[:floors].detect{|o| o[:id] == floor_id} || {id: floor_id, name: floor_name, rooms: []}
  house[:floors] |= [floor]

  room = floor[:rooms].detect{|o| o[:name] == room_name} || {name: room_name, furnitures: []}
  floor[:rooms] |= [room]

  furniture = room[:furnitures].detect{|o| o[:name] == furniture_name} || {name: furniture_name}
  room[:furnitures] |= [furniture]

  results
end

答案 1 :(得分:1)

为什么不使用deep_pluck来获取嵌套关联。

House.where(city: 'Paris').deep_pluck(
  :name, 
  floors: [
    :id, 
    :name, 
    rooms: [
      :name,
      furnitures: :name,
    ]
  ]
)