2014-10-17 58 views
1

我正在準備一個API來使用AngularJS應用程序。這個應用程序將提供一個用於管理數據庫中的人員的儀表板,因此個人主頁面吸引了大量信息。下面是我使用的格式化信息作爲JSON的Jbuilder的文件:如何通過Rails API提供JSON時最小化查詢?

json.extract! @person, :id, :employee_id, :display_name 
json.appointments @person.appointments, :id, :jobcode, :title 
json.flags @person.flags, :id, :name 
json.source_relationships @person.source_relationships, :id, :source_id, :target_id, :relationship_type_id 
json.target_relationships @person.target_relationships, :id, :source_id, :target_id, :relationship_type_id 

的JSON返回這個樣子的(從/api/v1/people/1685.json):

{ 
    "id":1685, 
    "employee_id":"9995999", 
    "display_name":"John Doe", 
    "appointments": [ 
    {"id":353,"jobcode":"TE556","title":"Developer"} 
    ], 
    "flags":[ 
    {"id":5,"name":"Unclassified"}, 
    {"id":7,"name":"Full Time"} 
    ], 
    "source_relationships":[ 
    {"id":19,"source_id":1685,"target_id":1648,"relationship_type_id":9}, 
    {"id":21,"source_id":1685,"target_id":1606,"relationship_type_id":9} 
    ], 
    "target_relationships":[ 
    {"id":1,"source_id":1648,"target_id":1685,"relationship_type_id":10} 
    ] 
} 

和控制檯顯示了這些疑問:

Person Load (0.1ms) SELECT `people`.* FROM `people` WHERE `people`.`id` = 1685 LIMIT 1 
Appointment Load (0.1ms) SELECT `appointments`.* FROM `appointments` WHERE `appointments`.`person_id` = 1685 
Flag Load (0.1ms) SELECT `flags`.* FROM `flags` 
    INNER JOIN `flags_people` ON `flags`.`id` = `flags_people`.`flag_id` WHERE `flags_people`.`person_id` = 1685 
Relationship Load (0.1ms) SELECT `relationships`.* FROM `relationships` WHERE `relationships`.`source_id` = 1685 
Relationship Load (0.1ms) SELECT `relationships`.* FROM `relationships` WHERE `relationships`.`target_id` = 1685 

我喜歡JSON格式化的方式,但它必須運行5個單獨的查詢似乎效率低下。我嘗試將joins()includes()方法添加到活動記錄查詢中,該查詢當前只是:@person = Person.find(params[:id]),但這似乎並不是我想要的。我怎樣才能乾淨地儘量減少查詢的數量,同時仍然以類似的格式返回JSON?

+0

解釋你的意思是「似乎並沒有成爲我想要的嗎?」什麼。你顯然想要一些渴望的加載。 'Person.joins(:flags,:appointments,:source_relationships,:target_relationships).find(params [:id])'(或者因爲你沒有展示你的模型會發生什麼)與你想要的有什麼不同? – ptd 2014-10-17 15:18:53

+0

優化和json格式無關彼此 – phoet 2014-10-17 15:42:35

+0

@ptd - 看起來您所建議的查詢是將所有必需的表連接到'people'表,但附加查詢('SELECT * FROM appointmentments','SELECT * FROM flags'等)仍在運行。這就是爲什麼我認爲'join()'不是我想要的方法。我用'includes()'遇到了同樣的情況。 – Shaun 2014-10-17 16:06:03

回答

2

我在找的方法是eager_load。不知道我過去怎麼沒遇到過它,但它將所有表格查詢合併爲一個使用LEFT OUTER JOIN

@person = Person.eager_load(:flags, :appointments, 
:source_relationships, :target_relationships).find(params[:id]) 

結果這個單號查詢:

SELECT DISTINCT `people`.`id` FROM `people` 
LEFT OUTER JOIN `flags_people` ON `flags_people`.`person_id` = `people`.`id` 
LEFT OUTER JOIN `flags` ON `flags`.`id` = `flags_people`.`flag_id` 
LEFT OUTER JOIN `appointments` ON `appointments`.`person_id` = `people`.`id` 
LEFT OUTER JOIN `relationships` ON `relationships`.`source_id` = `people`.`id` 
LEFT OUTER JOIN `relationships` `target_relationships_people` ON `target_relationships_people`.`target_id` = `people`.`id` 
WHERE `people`.`id` = 1685 LIMIT 1 

上找到this blog post from Arkency