2014-10-17 31 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