如何设计 RESTful 高级搜索/过滤器

Posted

技术标签:

【中文标题】如何设计 RESTful 高级搜索/过滤器【英文标题】:How to desing RESTful advanced search/filter 【发布时间】:2015-05-20 04:04:35 【问题描述】:

首先,我已经阅读了RESTful URL design for search 和How to design RESTful search/filtering? 的问题。我正在尝试设计更高级的选项,以简单和 RESTful 方式进行搜索。 这些问题的答案给了我一些关于如何设计我以前的应用程序 url 模式以实现搜索/过滤功能的见解和线索。

首先,我使用模式为基本过滤选项想出了一个非常好的和简单的解决方案:

Equality search: key = val

IN search: key = val1 & key = val2

但随着应用程序的增长,搜索需求也在增长。最后,我为高级搜索选项提供了一些相当不愉快且复杂的 url 模式,其中包括:

Negation search: key-N = val

Like search: key-L = val

OR search: key1-O = val1 & key2 = val2

Range search: key1-RS = val1 & key1-RE = val2

还有,除了filters,query还要获取分页和order by的信息,所以filter参数有F-后缀,order by字段有O-后缀,分页有P-后缀。

我希望此时我不必补充说,解析此类请求是相当恶意的任务,如果密钥包含“-”,则可能会产生歧义。我创建了一些正则表达式来解析它,它现在工作得很好,但是......

现在我开始编写一个新的网络应用程序,我有机会从头开始重新设计这件作品。

我想知道在浏览器中以结构化和不言自明的方式创建包含所有信息的对象,并将其作为 JSON 字符串发送到服务器,例如:

filter = 'type':'like','field':key,'value':val1,'operator':'and','negation':false,..

但我有一种奇怪的感觉,这不是一个好主意——我真的不知道为什么。

所以,这将是我的上下文的定义。现在的问题:

我正在寻找更简单、更安全的模式来实现高级搜索,包括我上面提到的作为 RESTful GET 参数的选项 - 你能分享一些想法吗? 或者也许有一些关于不以 RESTful 方式执行此操作的见解? 另外,如果您看到 JSON 方式的一些缺陷,请分享。

编辑:

我知道是什么让 json 作为 get 参数发送,这不是一个好主意。对其进行编码 - 使其丑陋且难以阅读。

由 thierry templier 发送的链接提供的信息给了我一些思考,我设法在 GET 参数中设计了更一致和安全的过滤器处理。下面是语法的定义。

对于过滤器 - 多个 F 参数(每个搜索条件一个):

F = OPERATOR:NEGATION:TYPE:FIELD:VAL[:VAL1,:VAL2...]

允许的值:

[AND|OR]:[T|F]:[EQ|LI|IN|RA]:FIELD_NAME:VALUE1:VALUE2...

对于 order by - 多个 O 参数(每个有序字段一个):

O = ODINAL_NO:DIRECTION:FIELD

允许的值:

[0-9]+:[ASC|DESC]:FIELD_NAME

分页-单个P参数:

P = ITEMS_PER_PAGE:FROM_PAGE:TO_PAGE

我认为这将是一个很好的解决方案——它满足了我的所有要求,易于解析和编写,易于阅读,而且我看不出语法会变得模棱两可。

我非常感谢您对这个想法的任何想法 - 您是否发现任何缺陷?

【问题讨论】:

那么你最终得到了什么?我现在正在尝试实现类似的 API,并且正在尝试找到一种表示“括号”的方法,例如 (key1:value1 OR key2:value2) AND (key3:value3 OR key4:value4)。 是的,它工作得很好。工作的朋友建议使用polish notation 作为括号 - 它易于创建和解析,并且非常适合 url 查询。我们以略微修改的方式实现了它,以便在前端与 devextreme 网格一起使用,在 .netCore 中间件上解析为 sql 并发送到 oracle 和 mssql 数据库。它提供了一种非常简单的方法,可以从任何 sql 查询中快速生成带有网格的功能齐全的屏幕。 谢谢,会试试的! 【参考方案1】:

这里有几个选项。但很明显,如果您的查询往往带有复杂的运算符,等等......您不能使用一组查询参数。我看到了两种方法:

将查询作为 JSON 内容提供给方法 POST 在具有特定格式/语法的查询参数中将查询提供给方法GET

我认为您可以看看 ElasticSearch 用于他们的查询。他们能够用 JSON 内容描述非常复杂的查询(使用多个级别)。这是他们查询 DSL 的链接:http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html

您还可以查看 OData 对查询的作用。他们选择使用单个查询参数$filter 的另一种方法。以下是一些可以为您提供示例的链接:https://msdn.microsoft.com/en-us/library/hh169248(v=nav.70) 和 http://www.odata.org/documentation/odata-version-3-0/url-conventions/。此选项需要在服务器端有语法来解析您的查询。

一般来说,此链接还可以在其“过滤数据”部分中为您提供此级别的一些提示:https://templth.wordpress.com/2014/12/15/designing-a-web-api/。

希望它为您在 RESTful 服务中设计查询提供一些有用的提示;-)

蒂埃里

【讨论】:

以上是关于如何设计 RESTful 高级搜索/过滤器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用angularjs添加动态过滤功能来处理高级搜索?

如何使用输入文本和选择对数据表应用高级搜索?

Sharepoint Online 高级搜索日期过滤器失败

Laravel:高级搜索表单查询

Extjs - 高级搜索表单

Outlook 高级搜索属性 GlobalAppointmentID