2014-10-10 66 views
0

這對於Asana來說有點冗長,並且它非常「不那麼靈活」,並且「對於API來說是一種」剩下的願望「,如果重複項目可以用其他任何方式完成,那麼這個。我可以用其他方式重複一個體式項目嗎?

首先,我必須說明我喜歡Asana,並通過他們的網站在其中工作。所以我不反對它,或者與它的API有任何爭執。如果你還沒有,你應該嘗試一下,除非你想要/不得不通過他們的API來編寫針對Asana平臺的東西。


我本週早些時候發佈了關於複製一個項目,你可以在這裏找到一個問題: Copy an Asana task/project

問題是簡單地說,你可以複製一個項目或一組與體位API任務。來自Agnoster的答案僅僅是,現在這是不可能的,但它在積壓之中。

因此,我寫了一些實際上覆制項目的代碼(見下文),然後用所有任務和子任務重新創建整個項目。這是一個相當昂貴的過程,因爲你必須分別查詢每個任務,這意味着如果我有10個任務,它將是1 + 10個查詢。一個查詢獲取項目包含10個任務的信息,然後我必須查詢每個任務以查看它是否包含任何子任務。 如果你在上面列出的每個任務中都有一個子任務,那麼你將不得不查詢他們的API 1 + 10 * 2次。想象一下,如果你有深層次的嵌套子任務,那麼最終可能會有幾百甚至上千個查詢。

我們目前有(在該項目中,我正在複製)50個任務,其中幾個子任務只有一個級別,這意味着大約1 + 50 + 50個請求。所以總共有大約101個查詢到他們的API。

現在我發現我從Asana查詢的任務缺乏信息。

我使用「/ projects/{project-id}/tasks」來獲取任務列表,以便對這些任務中的每一個和每個任務進行重複。然後我需要查詢每個任務這個「tasks/{task-id}/subtasks」以獲得每個子任務。非常直截了當。

現在的問題在於他們的API以及我從它那裏得到的回報,在這裏我希望有更好的解決方案。

如果我查詢這樣的: 「/項目/ {項目-ID} /任務」 我得到以下結果:

{ 
    "data": [ 
    { 
     "id": 1248, 
     "name": "Buy catnip" 
    }, 
    { 
     "id": 24816, 
     "name": "Reflect on role of kittens in society" 
    }, 
    { 
     ... 
    } 
    ] 
} 

有誰看到這裏的問題?也就是說,我只從服務器獲取ID和名稱,而沒有其他任何東西。一個任務由註釋,受讓人,創建日期,截止日期等組成,但該信息不在上面列表中列出,API端點「tasks/{task-id}/subtasks」也一樣。

那麼,我們在哪裏?那麼我將不得不再次查詢每一個任務,以獲得與實際任務相關的信息。所以我已經有很多的查詢快要增加一倍了。我的1 + 50 + 50查詢將最終爲1 + 50 + 50 + 50 + 50。因此,爲了通過他們的API複製這個項目,我會稍微超過200個查詢,以便從第一個項目獲得所有信息到第二個,但是等等,還有更多。這只是我實際查詢任務所需的查詢數量。然後,您將不得不再添加100個查詢,以便在新項目中創建所有新任務。

所以最終效果是,我想通過Asanas API複製到一個新項目的小項目將花費我大約301個查詢到達。即使是指示任務是否具有子任務的微小更新也會顯着減少查詢的數量。 (例如:{ 「ID」:1248, 「名」: 「買貓薄荷」, 「hasSubtasks」:假})

我的問題很簡單,有沒有什麼辦法來提高呢?我錯過了一些可以保存查詢並提高性能的重要API端點嗎?

下面是我寫來創建此代碼:

public bool DuplicateAsanaProject(string projectId) 
    { 
     // Get the current project 
     var request = new RestRequest(string.Format("/projects/{0}", projectId), Method.GET); 
     request.RequestFormat = DataFormat.Json; 

     var asanaProject = Execute<AsanaProjectTemplate>(request); 
     if (asanaProject == null) 
      return false; 

     // Create a new project 
     var newAsanaProject = CreateAsanaProjectInTeam(asanaProject.Data.Name, asanaProject.Data.Notes, TeamProductionId); 
     // Get all the tasks in the current project 
     var tasksInProject = GetAsanaTasksForProject(asanaProject.Data.Id); 
     // Reverse all the tasks to get them outputted in the correct order 
     tasksInProject.Data.Reverse(); 
     // Loop through all project tasks 
     foreach (var task in tasksInProject.Data) 
     { 
      // Get the task from the server 
      var oldTask = GetAsanaTask(task.Id); 
      // Create the new task 
      var newTask = CreateAsanaTask(oldTask.Data.Name, oldTask.Data.Notes, newAsanaProject.Data.Id, WorkspaceId); 

      // Get the sub-tasks for this task 
      var tasksList = GetAsanaTasksForTask(task.Id); 
      // If we have some sub-tasks, then create them 
      if (tasksList != null && tasksList.Data.Count > 0) 
       CreateSubTasksForTask(newTask.Data.Id, tasksList); 
     } 
     return true;    
    } 

    /// <summary> 
    /// Create sub-tasks for a specific task 
    /// </summary> 
    /// <param name="taskId">New task id. This is the task in where the new tasks will be added</param> 
    /// <param name="tasks">List all sub-tasks</param> 
    public void CreateSubTasksForTask(string taskId, AsanaTasksTemplate tasks) 
    { 
     // Reverse all the tasks to get them outputted in the correct order 
     tasks.Data.Reverse(); 
     foreach(var task in tasks.Data) 
     { 
      // Get the task from the server 
      var oldTask = GetAsanaTask(task.Id); 
      // Create the new task 
      var newTask = CreateAsanaSubTask(oldTask.Data.Name, oldTask.Data.Notes, taskId); 

      // Get the sub-tasks for this task 
      var tasksList = GetAsanaTasksForTask(task.Id); 
      // If we have some sub-tasks, then create them 
      if (tasksList != null && tasksList.Data.Count > 0) 
       CreateSubTasksForTask(newTask.Data.Id, tasksList); 
     } 
    } 

    /// <summary> 
    /// Retrieves all sub-tasks for a specific task 
    /// </summary> 
    /// <param name="taskId"></param> 
    /// <returns></returns> 
    public AsanaTasksTemplate GetAsanaTasksForTask(string taskId) 
    { 
     // Get all tasks in the current task 
     var request = new RestRequest(string.Format("tasks/{0}/subtasks", taskId), Method.GET); 
     request.RequestFormat = DataFormat.Json; 

     var result = Execute<AsanaTasksTemplate>(request); 
     return result; 
    } 

回答

1

簡短的回答是,是的!有一種方法可以控制返回的數據,它被稱爲opt_fields。因此,舉例來說: - 項目 所有任務 -

GET /projects/ID/tasks?opt_fields=name,notes,created_at,assignee.name,subtasks.name,subtasks.subtasks.name,subtasks.subtasks.subtasks.name

這將返回 他們的名字,備註,創建時間 - 受讓人,他們的名字 - 每個嵌套子任務達3級只有名字深

或者,opt_expand=.會爲任務提供所有「標準」字段,如果您只是要求該任務,您通常會返回該任務。

opt_expandopt_fields都記錄在開發人員文檔的Input/Output options部分。

+0

謝謝,這減少了電話100(在我的情況)。還有大約200個電話會完成我上面提到的項目的重複,相關嗎? – Patrick 2014-10-13 11:09:50

+0

假設您可以製作單個查詢以獲取所需的所有信息,則應該總共有101個查詢 - 1個GET獲取所有信息,然後100個個別POST請求創建每個任務(如果我瞭解您的目標正確)。然而,在實踐中,該GET將獲得大量數據,因此您可能仍然希望使用[pagination](http://developer.asana.com/documentation-preview/#Pagination)來獲得大塊,比如說25,一次 - 仍然會減少200個請求到4. – agnoster 2014-10-13 16:14:11

+0

這聽起來對我來說就像你真的只需要弄清楚你需要什麼字段,然後通過'opt_fields'請求它們作爲頂層和子任務級別(因爲你提到你只有一個級別的子任務)。因此,例如,如果您只需要名稱和備註,則可以使用'?opt_fields = name,notes,subtasks.name,subtasks.notes'。這消除了需要進行所有嵌套請求。如果在極少數情況下任務可能嵌套兩層,則還可以包含'subtasks.subtasks.id',然後在找到任何內容時手動抓取這些內容。 – agnoster 2014-10-13 16:16:58

相關問題