2014-09-29 34 views
20

我正在構建使用filter參數來控制搜索結果的REST API。例如,人們可以通過調用搜索用戶:REST API篩選器運營商最佳做法

GET /users/?filter=name%3Dfoo 

現在,我的API應該允許許多不同filter運營商。 數值運算符equalsgreater thanless than字符串運算containsbegins withends with日期運營商,如year oftimediff。此外,ANDOR組合應該是可能的。
基本上,我想支持底層MySQL數據庫運營商的一個子集。

我發現很多不同的實現(兩個很好的例子是Google AnalyticsLongJump)似乎使用自定義語法。
看着我的要求,我可能會設計一個自定義的語法相當類同MySQL的運算符的語法。
但是,如果有任何的最佳做法成立,我應該遵循和我是否應該考慮什麼事我不知道。謝謝!

+1

你有沒有試過/聽說過SPARQL? – 2014-09-29 16:21:51

+0

不,讓我看看 – Horen 2014-09-29 16:22:53

+0

看看[Solr queries](http://lucene.apache.org/core/2_9_4/queryparsersyntax.html)(它們也是通過HTTP GET完成的)。我也可以想象一個[MongoDB-like query](http://docs.mongodb.org/manual/tutorial/query-documents/)(帶有json和url編碼)。 – DanFromGermany 2014-10-08 13:43:49

回答

13

您需要一個已經存在的查詢語言,不要試圖重新發明輪子!通過REST這是複雜的,沒有完全解決的問題。有一些REST約束您的應用程序必須滿足:

  • 統一接口/超媒體作爲應用狀態的引擎:
    你必須超媒體響應發送到你的客戶,他們必須遵循這些給出的超鏈接反應,而不是自己建立請求。因此,您可以將客戶端與URI的結構分離。

  • 統一接口/自描述消息:
    您必須發送帶有語義註釋的消息。所以你可以將客戶端從數據結構中分離出來。最好的解決方案是RDF,例如打開鏈接的數據詞彙。如果你不想使用RDF,那麼第二個最好的解決方案就是使用供應商特定的MIME類型,所以你的消息將是自描述性的,但客戶需要知道如何解析你的自定義MIME類型。

爲了描述簡單的搜索鏈接,您可以使用URI templates,例如GET /users/{?name}將等待在查詢字符串name參數。您可以使用hydra vocab中的hydra:IRITemplateMapping將語義添加到參數name

描述ad-hoc查詢是一項艱鉅的任務。你必須以某種方式描述你的查詢可以包含什麼。

  • 你可以選擇一個URI查詢語言,並堅持URI模板,可能hydra註釋。有很多已經存在的URI query languages,如HTSQL,OData query(人工智能不喜歡那個)等等...

  • 您可以選擇一種現有的查詢語言並將其發送到一個URI參數中。這可以是任何你想要的,例如SQL,SPARQL等......你必須教你的客戶端來生成這個參數。您可以創建自己的詞彙來描述實際查詢的約束條件。如果你不需要複雜的東西,這應該不成問題。我不知道已經存在的查詢結構描述詞彙,但我從來沒有找過它們......

  • 您可以選擇一個現有的查詢語言,並在SEARCH request正文中發送它。 Afaik SEARCH不會被最近的HTTP客戶端緩存或支持。它由webdav定義。您可以使用適當的MIME類型來描述您的查詢,並且可以使用與以前解決方案相同的詞彙表。

  • 您可以使用RDF查詢解決方案,例如SPARQL endpointtriple pattern fragments等...因此,您的查詢將包含語義元數據,而不是您的鏈接描述。通過SPARQL,您不需要三重數據存儲,您可以將服務器端的查詢轉換爲SQL或任何您使用的查詢。您可以使用SPIN來描述查詢約束和查詢模板,但這對我來說也是新的。可能有其他的解決方案來形容SPARQL查詢結構...

所以總結,如果你想真正的REST的解決方案,你要描述你的客戶,他們可以如何構建查詢和什麼參數,邏輯他們可以使用的運營商沒有查詢描述,他們將無法爲用戶生成例如HTML表單。如果你不想使用REST解決方案,那麼選擇一種查詢語言在客戶端上編寫一個構建器,在服務器上編寫一個解析器,就這些了。

2

通過擁抱一套通用的公認的分隔符,可以直接實現 的等式比較。使用這些 分隔符將filter query-string參數的值設置爲字符串將創建一個名稱/值對列表,可以在服務器端輕鬆解析這些名稱/值對,並根據需要使用 來增強數據庫查詢。您可以使用選擇的分隔符(「|」)將OR和(「&」)的單個過濾器短語分開以單獨使用 個別過濾器短語AND和雙冒號(「::」),以將名稱和值。 這提供了一組足夠獨特的分隔符來支持大多數用例,並創建一個用戶可讀的 查詢字符串參數。一個簡單的例子將有助於澄清這項技術。假設我們想要 請求居住在「丹佛」名稱爲「Todd」並且標題爲「Grand Poobah」的用戶。

請求URI,完整的查詢字符串可能是這樣的:

GET http://www.example.com/users?filter=「名稱::託德&城市::丹佛&標題::盛大普巴爾」

雙重的分隔符冒號(「::」)將屬性名稱與比較值 分開,使比較值可以包含空格,從而更容易從服務器上的值 解析定界符 請注意,名稱/值對匹配將是的屬性的名稱由有效載荷中的服務返回的。

大小寫敏感性肯定會在個案的基礎上進行辯論,但一般來說, 過濾在忽略大小寫時效果最佳。您還可以根據需要使用星號 (「*」)作爲名稱/值對的值部分提供通配符。 對於需要更簡單的平等或通配符比較的查詢,需要引入運算符 。在這種情況下,操作員本身應該成爲值的一部分,並在服務器端進行解析,而不是屬性名稱的一部分。當 需要複雜的查詢語言風格的功能,可考慮從開放數據協議(OData的)引入查詢概念過濾系統查詢 選項規格(http://www.odata.org/documentation/odata-version-4-0/

+3

你的回答看起來不像**建立的最佳實踐**(OP的問題),它看起來更像特設意見。你可以添加引用來源這種過濾器使用? – xmojmr 2014-10-08 15:59:08

+1

這個答案似乎是從http://www.restapitutorial.com/resources.html複製粘貼的(請參閱PDF文檔,第27/28頁,截至2016年11月4日) – CharlyDelta 2016-11-04 11:47:07

9

The Open Data Protocol (OData)

您可以檢查BreezeJs太多,看看這個協議它是用breeze-mongodb模塊爲node.js + mongodb實現的,以及用於Breeze.ContextProvider dll的使用Web API和EntityFramework的.NET項目。

0

似乎有很多標準(如OData),但許多標準很複雜,因爲它們引入了新的語法。

對於簡單的多濾波以下格式避免污染參數的命名空間,同時仍然站在現有網絡技術的頂部

GET /users?filter[name]=John&filter[title]=Manager 

這是容易閱讀和在後端語言,如PHP將接收它作爲陣列要應用的過濾器。

+1

「或」過濾器是什麼? – Horen 2017-06-20 08:21:44

+0

落入非簡單;-)你可以在兩個請求中做到這一點。我想你可以像'GET/users?filterOr [0] [name] = John&filterOr [0] [name] = Eva' – 2017-07-05 10:08:00