REST和复杂的搜索查询 [英] REST and complex search queries

查看:75
本文介绍了REST和复杂的搜索查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种在REST API中建模搜索查询的强大方法。

I'm looking for a robust way to model search queries in a REST api.

在我的api中,您可以在URI的URI中指定搜索条件资源使用查询参数。

In my api, you can specify the search criteria in the URI of a resource using query parameters.

例如:

/ cars?search = color ,蓝色; AND;门,4 - >返回4门蓝色车辆列表

/ cars?search = color,blue; OR; door, 4 - >返回蓝色或有4个门的汽车列表

在服务器端,搜索字符串映射到所需的基础技术。根据其他资源,这可以是SQL查询,Hibernate Criteria api,另一个Web服务调用,...

On the server side, the search string is mapped to the desired underlying technology. Depending on the rest resource, this can be a SQL query, the Hibernate Criteria api, another webservice call, ...

这2个示例很简单,可以支持,但是我还需要更复杂的搜索功能,如子字符串搜索,日期之前/之后搜索,NOT,...

The 2 examples are simple enough to support, but I also need more complex search features like substring search, searching before/after dates, NOT, ...

这是我认为的常见问题。是否有我可以使用的库(或模式):

This is a common problem I think. Is there a library (or a pattern) that I can use that:


  • 将指定为字符串的搜索查询映射到通用标准模型。搜索格式不必与上面列出的相同。

  • 允许我将Criteria模型映射到我需要使用的任何技术

  • 为Hibernate / JPA / SQL提供映射支持,但这是奖励;)

  • Maps search queries specified as a string to a generic Criteria model. The search format does not have to be the same as I listed above.
  • Allows me to map that Criteria model to any technology I need to use.
  • Offers mapping support for Hibernate/JPA/SQL, but this is a bonus ;)

亲切的问候,

格伦

推荐答案

每当我遇到这些问题时,我问自己如果我正在创建传统网页,我将如何向用户展示?简单的答案是我不会在一个页面中提供这些选项。界面太复杂了;但我能做的是提供一个界面,允许用户在多个页面上建立越来越复杂的查询,这是我认为在这种情况下应该采用的解决方案。

Whenever I face these problems, I ask myself "How would I present this to a user, if I was creating a traditional webpage"? The simple answer is that I wouldn't present those sort of options in a single page. The interface would be too complex; however what I could do is provide an interface that allowed users to build up more and more complex queries over a number of pages and that's the solution I think you should go for in this case.

HATEOAS约束指定我们必须在回复中包含超媒体控件(链接和表单)。因此,假设我们在 / cars 中有一个带有搜索选项的分页车辆集合,这样当你得到 / cars 它返回类似的东西(顺便说一下,我在这里使用自定义媒体类型,但表格和链接应该非常明显。如果不是,请告诉我):

The HATEOAS constraint specifies that we must include the hypermedia controls (links and forms) in our responses. So let's say we have a paginated collections of cars at /cars with a search option, so that when you get /cars it returns something like (BTW I'm using a custom media-type here, but the forms and links should be pretty obvious. Let me know if it isn't):

<cars href="/cars">
    <car href="/cars/alpha">...</car>
    <car href="/cars/beta">...</car>
    <car href="/cars/gamma">...</car>
    <car href="/cars/delta">...</car>
    ...
    <next href="/cars?page=2"/>
    <search-color href="/cars" method="GET">
        <color type="string" cardinality="required"/>
        <color-match type="enumeration" cardinality="optional" default="substring">
            <option name="exact"/>
            <option name="substring"/>
            <option name="regexp"/>
        </color-match>
        <color-logic type="enumeration" cardinality="optional" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </color-logic>
    </search>
    <search-doors href="/cars" method="GET">
        <doors type="integer" cardinality="required"/>
        <door-logic type="enumeration" cardinality="required" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </door-logic>
    </search>
</cars>

所以只要说我们搜索白色汽车,我们就会获得 / cars? color = white 我们可能会得到类似的信息:

So just say we search for white cars, we would GET /cars?color=white and we might get back something like:

<cars href="/cars?color=white">
    <car href="/cars/beta">...</car>
    <car href="/cars/delta">...</car>
    ...
    <next href="/cars?color=white&page=2"/>
    <search-color href="/cars?color=white" method="GET">
        <color2 type="string" cardinality="required"/>
        <color2-match type="enumeration" cardinality="optional" default="substring">
            <option name="exact"/>
            <option name="substring"/>
            <option name="regexp"/>
        </color2-match>
        <color2-logic type="enumeration" cardinality="optional" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </color2-logic>
    </search>
    <search-doors href="/cars?color=white" method="GET">
        <doors type="integer" cardinality="required"/>
        <door-logic type="enumeration" cardinality="required" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </door-logic>
    </search>
</cars>

这个结果让我们改进我们的查询。所以只是说我们想要白色车而不是灰白色车,我们可以GET'/ cars?color = white& color2 = off-white& color2-logic = not',这可能会返回

This result then let's us refine our query. So just say we wanted white cars but not "off-white" cars, we could then GET '/cars?color=white&color2=off-white&color2-logic=not', which might return

<cars href="/cars?color=white&color2=off-white&color2-logic=not">
    <car href="/cars/beta">...</car>
    <car href="/cars/delta">...</car>
    ...
    <next href="/cars?color=white&color2=off-white&color2-logic=not&page=2"/>
    <search-color href="/cars?color=white&color2=off-white&color2-logic=not" method="GET">
        <color3 type="string" cardinality="required"/>
        <color3-match type="enumeration" cardinality="optional" default="substring">
            <option name="exact"/>
            <option name="substring"/>
            <option name="regexp"/>
        </color3-match>
        <color3-logic type="enumeration" cardinality="optional" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </color3-logic>
    </search>
    <search-doors href="/cars?color=white&color2=off-white&color2-logic=not" method="GET">
        <doors type="integer" cardinality="required"/>
        <door-logic type="enumeration" cardinality="required" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </door-logic>
    </search>
</cars>

我们可以进一步细化我们的查询,但重点是在整个过程中的每一步,超媒体控件告诉我们什么是可能的。

We could then further refine our query, but the point is that at each step along the way, the hypermedia controls tells us what is possible.

现在,如果我们考虑汽车的搜索选项,颜色,门,品牌和型号都不是无界限的,所以我们通过提供枚举可以使选项更明确。例如

Now, if we think about the search options for cars, the colors, doors, makes and models aren't unbounded, so we could make the options more explicit by providing enumerations. For instance

<cars href="/cars">
    ...
    <search-doors href="/cars" method="GET">
        <doors type="enumeration" cardinality="required">
            <option name="2"/>
            <option name="3"/>
            <option name="4"/>
            <option name="5"/>
        </doors>
        <door-logic type="enumeration" cardinality="required" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </door-logic>
    </search>
</cars>

然而我们唯一的白色车可能是2门和4门,在这种情况下GETing / cars?color = white 可能会给我们

However the only white cars that we have might be 2 and 4 door, in which case GETing /cars?color=white might give us

<cars href="/cars?color=white">
    ...
    <search-doors href="/cars?color=white" method="GET">
        <doors type="enumeration" cardinality="required">
            <option name="2"/>
            <option name="4"/>
        </doors>
        <door-logic type="enumeration" cardinality="required" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </door-logic>
    </search>
</cars>

同样,当我们改进颜色时,我们可能会发现它们只有几个选项,在这种情况下我们可以从提供字符串搜索切换到提供枚举搜索。例如,GETing / cars?color = white 可能会给我们

Similarly, as we refine the colors, we might find their are only a few options, in which case we can switch from providing a string search, to providing an enumeration search. e.g., GETing /cars?color=white might give us

<cars href="/cars?color=white">
    ...
    <search-color href="/cars?color=white" method="GET">
        <color2 type="enumeration" cardinality="required">
            <option name="white"/>
            <option name="off-white"/>
            <option name="blue with white racing stripes"/>
        </color2>
        <color2-logic type="enumeration" cardinality="optional" default="and">
            <option name="and"/>
            <option name="or"/>
            <option name="not"/>
        </color2-logic>
    </search>
    ...
</cars>

您可以对其他搜索类别执行相同操作。例如,最初您不想枚举所有品牌,因此您将提供某种文本搜索。一旦集合被细化,并且只有几个模型可供选择,那么提供枚举是有意义的。同样的逻辑适用于其他集合。例如,你不想列举世界上所有的城市,但是一旦你将这个区域精炼到10个左右的城市,那么枚举它们会非常有帮助。

You could do the same for other search categories. For instance, initially you wouldn't want to enumerate all the makes, so you would provide some sort of text search. Once the collection has been refined, and there are only a few models to pick from, then it makes sense to provide an enumeration. The same logic applies to other collections. For instance you wouldn't want to enumerate all of the cities in the world, but once you have refined the area to 10 or so cities, then enumerating them can be very helpful.

是否有图书馆会为您执行此操作?没有我知道的。我见过的大多数人甚至不支持超媒体控件(例如,你必须自己添加链接和表单)。你有可以使用的模式吗?是的,我相信以上是解决此类问题的有效模式。

Is there a library that will do this for you? None that I know of. Most I've seen don't even support hypermedia controls (i.e., you've got to add the links and forms yourself). Is there a pattern you can use? Yes, I believe the above is a valid pattern for solving this sort of problem.

这篇关于REST和复杂的搜索查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆