2010-08-18 26 views
6

我有REST API實現以下是休息只是還給這些文件的基本文件和裁判原則HOWTO得到其他的東西等等等等的RESTful API排序困境

例如A /車/ 5會給我的模型: blabla,user_id:1,然後如果你需要所有者,你會得到/用戶/ 1來獲取用戶數據..

這種方式連接和東西都避免在數據庫中..所有東西之間的鏈接本身和數據互連在休息客戶端部分 - 保持簡單的事情很容易緩存/下降緩存,規模等

但是當你需要排序會發生什麼?

想象一下,我們對前端顯示以下數據有一些看法: 汽車模型,用戶名等等,並且您想按用戶名排序。

你真的不能告訴/車/ 5的用戶名進行排序的原因只知道用戶ID ...

一種選擇我看到的是從用戶/用戶/列表排序?sortby =用戶名和然後將那些返回的ID實際上與汽車相關聯。但這意味着我們需要獲得所有用戶......並且只使用那些似乎是殺手性能瓶頸的部分。

感謝任何指針

回答

5

我想你想避免參加的所有錯誤的原因,採取這種方法,你將不得不以服務更多的請求。

如果您將所有顯示的信息(即聯接數據庫端)帶回來,則客戶端將不得不減少查詢次數,並且您可以在不需要()懶)加載所有的子對象。

另一種選擇是將子對象作爲子XML元素(與OpenStreetMap的RESTful接口工作方式類似)。您仍然有來自客戶端的單擊,您應該能夠優化查詢以最大限度地減少數據庫負載。

4

如果您要避免服務器中的所有連接並將其留給客戶端,那麼在這種情況下,您必須保留對客戶端的排序。這是因爲必須進行加入才能按用戶名分類汽車。

您可以創建另一個名爲CarsAndOwners或類似的資源,它返回加入的列表,此時在服務器上進行排序是合理的。

2

我通過想象,我想寫,比如REST風格的理想開始查詢:

/car/list?sortby=username 

然後找出如何實現。

現在你列表方法讓你對象,你說,不公開用戶名,但我不認爲事情。在列表準備好之前,所有的排序都應該在服務器上進行。

你將需要加入你的對象用戶在某些時候對象爲了做到這一點,而且也沒有迴避這個問題的辦法。你有唯一的選擇就是你做的地方。

如果您正在使用傳統的RDBMS,那麼在數據庫級別執行該操作是有意義的。


在應用程序API和數據庫之間使用ORM層嗎?

+0

好所有的堅持是在REST後面......目前休息是使用ORM,但我不認爲這是相關的。 – 2010-08-18 10:15:31

+1

我得到了你使用ORM的提示,因爲你說你在DB上避免了連接,並且連接了REST應用層中的所有對象。 我可以看到這個簡單幹淨的建築的吸引力,但它可能是你目前困境的根源。 爲了讓應用程序正常工作,我會考慮妥協這個體系結構:在數據庫上有額外的存儲過程或視圖,它們會返回預先排序好的數據,併爲這些對象提供ORM映射,並讓REST應用程序選擇取決於查詢的方法之間。 – 2010-08-19 09:55:24

2

首先,你的榜樣/car/5應該是資源的多個版本,以REST式:如果你想有一個RESTful方法來排序,你可以做到這一點現在

/cars/5 
/users/1 

,一般來說:

/cars?sort=make&order=asc 

在你的例子中,你提到你想按用戶名排序汽車。但是,就像你提到的那樣,cars集合應該對users一無所知。因此,如果您想顯示汽車列表並按用戶進行分組,您會做什麼?您需要一種方法來檢索這些信息。這樣做的一種方式是通過用戶環路,並要求與每個用戶相關的汽車:

# pseudo code 

users.each do |user| 
    # assuming the user id is 5, 
    # to display the user's cars, 
    # we need to request /users/5/cars 
end 

因此,我們可以在像/users/5/cars URL請求車爲每個單獨的列表。這被稱爲嵌套資源。我們只請求與用戶5相關的汽車。

但是,您有可能向您的API發出大量請求的問題(根據您的使用情況可能會有所不同)。

另一種方法,這可能是更好的,是做這一個請求:

/users/cars?sort=username&order=asc 

這將返回由用戶名訂購用戶和他們的汽車的數組。

而另一種方法可以是:

/users?include=[cars]&sort=username&order=asc 

,但我不喜歡這種方法不亞於先前。我會推薦以前的方法/users/cars

備註:您的列表應該進行分頁,以便當您僅顯示部分列表時,不會請求全部的開銷。

/users?page=1&per_page=50 
+1

多元資源命名不是REST的必要條件 - 對於每種資源的可供性都要求統一的語義:意思是說,每個暴露的資源應該以相同的方式(從消費者的角度來看)到可用的協議方法(GET,POST ,DELETE等) – 2013-10-27 05:59:36

1

數據庫設計做的加入迅速,因此留給了客戶端或服務器應用程序沒有道理給我。

我在REST上讀到的幾乎所有東西都說實體/資源之間的關係也應該是一種資源。因此,您應該有一個資源/mydomain.com/CarsAndUsers表示該加入/關係。

然後,你可以做的是資源,就像任何其他排序,它會通過數據庫進行處理:

/mydomain.com/CarsAndUsers?sortby=username

您還可以應用過濾來該資源(和分頁)就像任何其他資源一樣。

編輯:

按照該意見,將是更好的做這樣的事情:

/汽車嵌入=用戶,sortby =用戶名

感謝埃裏克指點這一點。

+0

這是API端點組合爆炸的祕訣。更常見的RESTful方法是使用參數來請求內聯對象(基本上是聯合表示)。例如:'/ albums?embed = artist'。這些可用於嵌入的資源可以在超媒體「鏈接」集合中包含鏈接,以使該選項可被發現。 – 2013-10-27 06:03:11

+0

謝謝Eric,雖然我同意你關於端點爆炸的觀點,但問題不是關於相關對象,而是關於基於相關集合的屬性對一個集合進行排序的問題。我不確定你的建議是否解決了這個問題。或者你是說OP可以做到這一點: /cars?embed = user,sortby = username – rmcsharry 2014-04-19 11:20:52

+0

是的,這幾乎就是我的建議。 – 2014-04-22 17:37:53