2014-10-17 1 views
1

AngularJS 앱을 제공하기위한 레일 API를 준비 중입니다. 이 응용 프로그램은 데이터베이스의 사람들을 관리하기위한 대시 보드를 제공하므로 개별 사용자의 기본 페이지에서 많은 정보를 가져옵니다.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에서)이 같은 모습을 반환 : 여기에 내가 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

+0

최적화 및 json 형식은 서로 아무 관계가 없습니다 – phoet

+0

@ptd - 제안 된 쿼리가 모든 필수 테이블을'people' 테이블에 조인하는 것처럼 보이지만 추가 쿼리 ('SELECT * FROM appointments','SELECT * FROM 플래그'등)가 계속 실행 중입니다. 그것이 내가'조인()이 내가 찾던 방법이 아니라고 생각한 이유입니다. 나는 includes()와 같은 상황을 만났다. – Shaun

답변

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

관련 문제