【问题标题】:Previous/next record based on search result基于搜索结果的上一条/下一条记录
【发布时间】:2017-02-22 14:32:14
【问题描述】:

一些背景

有问题的系统有大约一万条记录,允许用户通过“大量”不同搜索条件的数组进行浏览或搜索。然后将结果显示在分页表中,范围从几页到数据库中的每个结果。

如果用户进行了大量过滤并最终得到结果并单击任意记录,则她将被带到新视图/edit/{record_id},她可以在其中查看所述记录的所有详细信息。随时返回上一个搜索结果很容易,因为条件保留在搜索栏中,但是:

我正在努力实现的目标

如果用户要根据搜索结果进行大量更改,使用上一个和下一个按钮访问相邻记录而不返回结果会非常方便。

我已经能够使用ids 在基本级别上做到这一点

SELECT table.*, pn.p as previous_question, pn.n as next_question
   from table,
   (
       SELECT id, lead(id) OVER w as n, lag(id) OVER w as p
       FROM table
       window w as (order by id $order)
   ) as pn
   where table.id = $id
       and pn.id = $id

这显然只适用于记录与数据库中的记录顺序相同的最简单情况。我想要的是让他们在每种情况的数据顺序中工作。不用说,对这些数据进行排序的方法几乎是无限的。

我一直在想什么

创建某种函数/工具,让我可以阻止搜索 SQL 并像上面一样再次执行它,仅使用搜索条件和偏移量而不是 ids

保存一个列表结果中所有记录的顺序,可以是$_SESSION,数据库也可以是别的地方,然后简单的遍历列表得到ids我需要。

手头的工具

PHP、PostgreSQL、JS/jQuery。

TL;DR

无论用户点击“下一步”多少次,我都希望能够在不返回搜索的情况下获得下一个搜索结果。

---------

任何意见将不胜感激。相关文章的链接、处理方法甚至整个shebang ;)。能够在不消耗所有服务器内存或过多的数据库访问的情况下解决这个问题也很好,尽管资源在这里并不是真正的问题。

【问题讨论】:

  • 你为什么不像你建议的那样使用会话或cookie?这是一个很好的解决方案,并且会起作用。
  • 嗯,这是一个选项。我只是不觉得它对于包含可能 50k 项的数组非常优雅。另一方面,我可能只是在想这个。这就是为什么我想要一些输入:)
  • 分页通常是通过使用 sql LIMIT 命令的多个查询来完成的。
  • @jurgemaister 我不是说你应该保存结果数组!只是sql查询。只需保存不同的查询设置而不是结果!
  • 您将在会话中存储一个较低和较高的索引(在您的情况下,我猜是一样的),下一个/上一个按钮只会增加/减少索引。然后,您的 SQL 将有一个 LIMIT lowerindex,upper index。您也可以轻松存储用户建立的整个 SQL 查询。我不建议将整个返回的数组存储在会话中,因为这意味着当您应该在 SQL 中进行数据处理时,您必须在 PHP 中进行数据处理。

标签: php postgresql pagination paging


【解决方案1】:

我只是要把它扔在那里......你应该使用 Solr 或类似的东西,特别是如果这是一个SAS 并暴露给许多用户。

基本上尝试跟踪分页搜索结果然后进行遍历会导致您的应用中进行大量状态管理。

Solr(甚至只是简单的 postgres)的想法是为您的搜索(又名 OFFSETLIMIT)做一个开始和大小。 Solr 的速度如此之快,几乎不是性能问题。只需确保您对 Solr 或 Postgres 进行可预测的排序(又名 ORDER BY)。

如果您担心添加的新项目会导致分页消失,那就是:WHERE create time stamp is less than when we did the initial search

【讨论】:

  • Solr 看起来真的很有趣,而且确实是一个非常强大的工具。恐怕它超出了这个应用程序的范围,因为它是为只有少数用户使用的管理界面而设计的。因此,设置 Java 服务器是多余的。
  • 我的其他 cmets 仍然适用。只需使用 LIMIT 和 OFFSET 加上 WREATE TIME STAMP IS LESS THAN ... 和一个可预测的 ORDER BY。
  • 啊。想我明白你的意思了。所以通过例如以限制 3 和偏移量 n-1 重复搜索,我将获得当前、上一个和下一个记录。
  • 宾果游戏!我会说一些随机的东西,以便我达到评论的最低要求。
【解决方案2】:

我在这里看到了很多可能的问题。最大的问题是您正在尝试将无状态的 HTTP 请求映射到有状态的数据库操作,并且您正在尝试尽可能无状态地执行此操作。

我认为 REST 方式的优雅解决方案是使用导航按钮(后退 esp)和向下钻取以获取特定的详细记录。这样就可以将基本结果持久化在客户端,即浏览器缓存中。

通过这种方式,您必须使用后退按钮才能返回(可能是分页的)摘要搜索结果,但您不必回击即可返回搜索条件。

【讨论】:

  • 当我想到它时,它已经有点无国籍了。我输入所有搜索参数以填充搜索栏,因此我可以轻松地将它们再次拉出以执行查询。我同意这是最符合语义的方式,但我决定将最后执行的搜索查询存储在会话中,因为它更容易。耶懒惰!
  • 这不仅仅是什么更容易的问题。部分问题在于,当您必须为每个新查询添加限制和偏移量时,在会话 esp 中持久保存这样的结果集最终会对性能产生重大影响。如果您有一个更简单的系统“将结果列表发送给客户并让他们查看他们想要跟进的内容”,那么您可以避免这种情况并可能在每个详细信息页面上的主键上进行单个记录查找他们看着。
【解决方案3】:

存储搜索上下文,包括选定的过滤器、查询和排序顺序。可以选择将它们按内容散列存储,以便最终获得唯一的搜索上下文列表。

在详细信息页面的链接中包含指向已保存搜索上下文的链接,使用某种哈希。

在详细信息页面上,通过哈希检索搜索上下文并执行两次额外搜索,一次在同一方向上向前搜索,另一次向后搜索。通过在排序顺序定义中交换 asc 和 desc 来做到这一点。

在这两种情况下,将结果限制为 1 条记录,并添加一个附加子句以确保不包括当前详细记录。

这应该会为您提供上一个和下一个链接的正确记录。

可以在此处找到有关 Elasticsearch 的更详细答案:https://stackoverflow.com/a/42384125/401467

【讨论】:

    【解决方案4】:

    对于这个问题没有太多的解决方案。

    1 - 由于您的查询是动态构建的,因此您必须保留条件并在每次提供 LIMIT ... OFFSET 或直接提供 result_id 时执行查询(在 WITH 子句中使用 row_number 窗口函数)。

    2 - 你可以直接将结果集持久化在服务器中,我不建议使用会话来存储这么多的数据。

    3 - 或者您可以将 Collection 保存在客户端上,以 Json 发送整个结果集,然后使用 angularjs 或bonejs 之类的 Javascript 浏览它。我想如果你返回 10k 行,这也会很慢。

    我建议 1 或 3。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多