当前位置: 首页 > 面试题库 >

REST和复杂的搜索查询

关冠宇
2023-03-14
问题内容

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

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

例如:

/cars?search=color,blue;AND;doors,4 --> Returns a list of blue cars with 4 doors

/cars?search=color,blue;OR;doors,4 --> Returns a list of cars that are blue or have 4 doors

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

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

我认为这是一个普遍的问题。有没有可以使用的库(或模式):

  • 将指定为字符串的搜索查询映射到通用Criteria模型。 搜索格式不必与上面列出的相同。
  • 使我可以 将该Criteria模型映射到 我需要使用的 任何技术
  • 提供对Hibernate / JPA / SQL的映射支持,但这是一个好处;)

亲切的问候,

格伦


问题答案:

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

HATEOAS约束指定我们必须在响应中包括超媒体控件(链接和表单)。因此,假设我们有一个/cars带有搜索选项的分页汽车集合,这样当您获得/cars它时,它会返回类似(顺便说一句,我在这里使用的是自定义媒体类型,但是表单和链接应该很明显。让我知道不是):

<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>

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

<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>

然后,这个结果让我们优化查询。因此,只要说我们想要白色汽车而不是“灰白色”汽车,我们就可以获取’/ cars?color = white&color2 =
off-white&color2-logic = not’,它可能会返回

<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>

然后,我们可以进一步优化查询,但要点是,在此过程的每个步骤中,超媒体控件都会告诉我们什么是可能的。

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

<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可能会给我们

<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>

同样,在优化颜色时,我们可能会发现它们只是少数选项,在这种情况下,我们可以从提供字符串搜索切换到提供枚举搜索。例如,获取/cars?color=white可能给我们

<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个左右的城市,则对它们进行枚举将非常有帮助。

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



 类似资料:
  • 我有一张这样的桌子: 现在我想创建一个返回经过过滤的数据集的REST APIendpoint: 它应正确筛选API参数的任何组合。 所有参数都是可选的 看看这个示例: 我想要能够过滤基于每个参数或组合的2或参数。 我应该如何编写@RequestParam?这是一个复杂的查询。对此有何策略?

  • 我想从firebase搜索,其中的名字包含的字符从搜索框在任何位置的名字?有谁能像这样帮帮我吗

  • 我有以下格式的弹性搜索文档 } } 我的要求是,当我搜索特定字符串(string.string)时,我只想获得该字符串的FileOffSet(string.FileOffSet)。我该怎么做? 谢谢

  • 我需要使用Spring Boot REST和Spring Data JPA使用Criteria API实现复杂的搜索特性。我需要提供下面的RPI和和并键入[1,2,3] 拼贴对象具有、、字段和列表。它与具有关系,因此可以有一个或多个工作人员。 基于uri,我需要使用criteria API构建查询。 我发现实现的方法非常复杂。有没有这样的例子处理如此复杂的搜索过滤器? 提前道谢。

  • 如何将这个复杂的sql语句更改为JPQL? 这是否可以在JPQL表单中显示?

  • 我已经查看了其他各种StackOverflow答案,它们都与我的讲师在幻灯片中写的不同。 深度优先搜索的时间复杂度为O(b^m),其中b是搜索树的最大分支因子,m是状态空间的最大深度。如果m比d大得多,这很糟糕,但如果搜索树“浓密”,则可能比广度优先搜索快得多。 他接着说。。 空间复杂度为O(bm),即动作序列长度的空间线性!只需要存储从根到叶节点的单个路径,以及路径上每个节点的剩余未扩展兄弟节点