REST API过滤器运算符最佳实践

时间:2014-09-29 16:18:42

标签: api rest

我正在构建一个使用filter参数来控制搜索结果的REST API。例如,可以通过调用:

来搜索用户
GET /users/?filter=name%3Dfoo

现在,我的API应该允许许多不同的filter运算符。 数字运算符,例如equalsgreater thanless than字符串运算符,例如containsbegins withends with日期运算符,例如year oftimediff。此外,ANDOR组合应该是可能的 基本上,我想支持底层MySQL数据库运算符的一个子集。

我发现许多不同的实现(两个很好的例子是Google AnalyticsLongJump)似乎使用自定义语法。
看看我的要求,我可能会设计一个与MySQL运算符语法非常相似的自定义语法 然而,我想知道是否有任何最佳实践确定我应该遵循以及我是否应该考虑其他任何事情。谢谢!

4 个答案:

答案 0 :(得分:14)

您需要一种已有的查询语言,不要试图重新发明轮子!通过REST,这很复杂,并没有完全解决问题。您的应用程序必须满足一些REST约束:

  • 统一界面/超媒体作为应用程序状态的引擎:
    您必须向您的客户发送超媒体响应,他们必须遵循这些响应中给出的超链接,而不是自己构建请求。因此,您可以将客户端与URI的结构分离。

  • 统一界面/自描述信息:
    您必须发送带语义注释的消息。因此,您可以将客户端与数据结构分离。这样做的最佳解决方案是RDF,例如开放式链接数据词汇。如果您不想使用RDF,那么使用特定于供应商的MIME类型的第二个最佳解决方案,因此您的消息将是自描述的,但客户端需要知道如何解析您的自定义MIME类型。

要描述简单的搜索链接,您可以使用URI templates,例如GET /users/{?name}将在查询字符串中等待name参数。您可以使用hydra vocab中的hydra:IRITemplateMappingname等参数添加语义。

描述即席查询是一项艰巨的任务。您必须以某种方式描述您的查询可以包含的内容。

  • 您可以选择URI查询语言并坚持使用URI模板和可能的hydra注释。有很多已经存在的URI query languages,例如HTSQLOData query(ppl不喜欢那个),等等......

  • 您可以选择现有的查询语言并将其发送到单个URI参数中。这可以是你想要的任何东西,例如SQL,SPARQL等......你必须教你的客户生成那个参数。您可以创建自己的词汇来描述实际查询的约束。如果你不需要复杂的东西,这应该不是问题。我不知道已经存在的查询结构描述词汇,但我从来没有找过它们......

  • 您可以选择现有的查询语言,并在SEARCH request中将其发送到正文中。最近的HTTP客户端不缓存或支持Afaik SEARCH。它由webdav定义。您可以使用正确的MIME类型描述您的查询,并且您可以使用与之前的解决方案相同的词汇。

  • 您可以使用RDF查询解决方案,例如SPARQL endpointtriple pattern fragments等...因此,您的查询将包含语义元数据,而不是您的链接描述。通过SPARQL,您不需要三重数据存储,您可以将服务器端的查询转换为SQL,或者您使用的任何内容。您可以使用SPIN来描述查询约束和查询模板,但这对我来说也是新的。可能还有其他解决方案来描述SPARQL查询结构...

总而言之,如果您想要一个真正的REST解决方案,您必须向您的客户描述他们如何构建查询以及他们可以使用哪些参数,逻辑运算符。如果没有查询描述,他们将无法为用户生成例如HTML表单。如果您不想要REST解决方案,那么选择一种查询语言在客户端上编写构建器,在服务器上编写解析器,这就是全部。

答案 1 :(得分:9)

The Open Data Protocol (OData)

您也可以查看BreezeJs,看看它是如何使用breeze-mongodb模块为node.js + mongodb实现的协议,以及使用Web API实现.NET项目和使用Breeze.ContextProvider dll实现EntityFramework的.NET项目

答案 2 :(得分:3)

通过接受一套共同的,被接受的分隔符,可以实现平等比较 直截了当的时尚。使用这些参数将filter-string参数的值设置为字符串 分隔符创建一个名称/值对列表,可以在服务器端轻松解析并使用 根据需要增强数据库查询。您可以使用您选择的分隔符(“|”)来区分OR的单个过滤短语和("&")以分隔 AND的单独过滤短语和分隔名称和值的双冒号(“::”)。 这提供了一组足够独特的分隔符来支持大多数用例并创建用户可读的 query-string参数。一个简单的例子将用于澄清该技术。假设我们想要 要求名为“Todd”的用户居住在" Denver"并拥有“Grand Poobah”的称号。

请求URI以及查询字符串可能如下所示:

GET http://www.example.com/users?filter=" name :: todd& city :: denver& title :: grand poobah“

双冒号(“::”)的分隔符将属性名称与比较值分开, 使比较值包含空格 - 使得更容易从值中解析分隔符 在服务器上。 请注意,名称/值对中的属性名称将匹配将要属性的名称 由有效负载中的服务返回。

案例敏感性肯定会因个案而进行辩论,但总的来说, 当忽略大小写时,过滤效果最佳。您还可以使用星号根据需要提供通配符 (“*”)作为名称/值对的值部分。 对于需要多于简单相等或通配符比较的查询,引入运算符 有必要的。在这种情况下,运算符本身应该是值的一部分并在服务器上进行解析 一边,而不是属性名称的一部分。当复杂的查询语言风格的功能 需要考虑从开放数据协议(OData)过滤系统查询中引入查询概念 选项说明(http://www.odata.org/documentation/odata-version-4-0/

答案 3 :(得分:0)

似乎有很多标准(如OData),但很多标准都很复杂,因为它们引入了新的语法。

对于简单的多重过滤,以下格式避免污染参数名称空间,同时仍然站在现有的网络技术之上

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

它易于阅读,并且像PHP这样的后端语言会将其作为要应用的过滤器数组接收。

相关问题