【问题标题】:Elasticsearch get matching documents after specific document idElasticsearch 在特定文档 ID 后获取匹配文档
【发布时间】:2013-11-08 05:36:44
【问题描述】:

当我搜索文档时,我将前 10 个元素提供给视图,如果用户滚动到列表末尾,则应该显示接下来的 10 个元素。

我知道显示文档的最后一个文档 id,现在我必须获取下一个 10。基本上我会执行完全相同的搜索,偏移量为 10,但能够使用相同的搜索会好得多查询,将最后检索到的文档的文档 id 放入其中,并在具有该 id 的文档之后检索匹配的文档。

弹性搜索可以做到吗?

=== 更新

我想进一步指出我的问题,因为现在描述的似乎还不够清楚。很抱歉。

案例:

你有一种饲料,饲料每秒都会增长。如果用户访问提要,他会获得最近的 10 个条目,如果他向下滚动,他想获得接下来的 10 个条目。

由于提要每秒都在增长,因此通常的偏移量/限制(弹性搜索中的来自/大小)无法解决此问题,您将显示已显示的条目或完全更新的条目,具体取决于第一次请求之间的时间(第一次10 个条目)和下一个条目的请求。

在已经显示的条目之后获取下一个 10 个元素的请求为后端提供了显示的最后一个条目的 ID。后端知道忽略此特定条目之前的所有条目。

当我在代码中处理这个问题时,我从 Elasticsearch 请求包含所有匹配条目的列表并对其进行迭代,这样我就可以做我想做的一切(毫不奇怪)并提取所需的整体块。

我的问题是:在 elasticsearch 中是否有针对此问题的内置解决方案。因为在路上解决问题并不是最快的。

【问题讨论】:

  • 我不明白其中的区别。它只是您需要添加到查询以获取下一页的附加页面部分。您可以创建一个构造,为您创建可以附加到查询的页面查询部分
  • 它有所作为。将页面想象成 twitter 提要,如果用户向下滚动并准备好获取下一个元素,则可能会发生(当用户正在阅读前 10 个元素时)提要获得新条目。如果您通过简单的偏移选择接下来的 10 个元素,用户将检索他已经拥有的元素。
  • 可以用布尔查询排除一些id
  • 我建议使用文档索引“时间戳”,然后从 ES 中查询所有比 X 更新的项目。您可以为此使用范围过滤器。 elasticsearch.org/guide/en/elasticsearch/reference/current/…
  • @JulianHille 是的,这是一个好主意,它适用于大多数情况,谢谢。只是为了解释为什么它不能解决所有情况:提要可以按特殊条件排序,例如cmets 的数量。在这种情况下,排序不会响应创建的时间戳。但是对于我的大多数情况,您的想法很简单而且很棒。再次感谢。

标签: elasticsearch offset


【解决方案1】:

您只需要使用

创建查询 DSL 和分页系统

{ "size": 10, "from" : YOUR_OFFSET }

【讨论】:

  • 我的问题不是关于如何使用通常的偏移量和限制进行分页,这很清楚该怎么做。
  • 你仍然可以这样做。如果您从最旧的 -> 最新的文档中排序。只要您不删除项目,偏移量就应该适合您。
【解决方案2】:

这是一个老话题了,但感觉自elasticsearch 5.0 起就提供的Search After API 正是我们所需要的。提供上一个文档的 ID 和时间戳,例如:

GET twitter/tweet/_search
{
  "size": 10,
  "query": {
    "match": {
      "title": "elasticsearch"
    }
  },
  "search_after": [
    1463538857,
    "tweet#654323"
  ],
  "sort": [
    {
      "date": "asc"
    },
    {
      "_uid": "desc"
    }
  ]
}

来源:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-search-after.html

【讨论】:

    【解决方案3】:

    如果我正确理解了您的问题,那么您可以使用 ES 卷轴来处理此类问题。 这是一个关于如何在 java 中执行此操作的示例,请注意它使用 SearchType.SCAN

            SearchRequestBuilder requestBuilder = ....getClient().prepareSearch(indices)
    
            /**
             * Set up scroll and go from there.....
             * To do that need to change search type to <code>SearchType.SCAN</code>
             * and set up scroll it self
             * Once search type and scroll are set and search is executed, whoever
             * handles the result will need to check and poll the scroll
             */
            requestBuilder.setSearchType(SearchType.SCAN);
            requestBuilder.setScroll(new TimeValue(SCROLL_WINDOW_IN_MILLISECONDS)); // this is in MILLISECONDS
            requestBuilder.setSize(10); // this is how many hits per shrad per scroll will be returned
    
    
            SearchResponse response = requestBuilder.execute().actionGet();
            while (true) {
                results = client.prepareSearchScroll(results.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
                if (results.getHits().getHits().length == 0) {
                    break;
                }
                         // do what you need to do w/ scroll result here
    }
    

    所以每次在while 循环内,你都会得到 10 个连续的结果,直到你得到所有结果

    【讨论】:

    • 谢谢,你的回答说明没有办法直接用elasticsearch做,必须用代码来做。我还更新了我的问题,以便更好地指出我的问题。
    • 一切都可以通过 ES 提供的 REST API 直接完成。就我而言,我为此使用了 java API。这是一个关于如何通过 ES Rest API 执行相同操作的示例链接:www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-scroll.html
    • 我刚刚阅读了您的更新。我认为卷轴不会为您服务,因为卷轴是快照,这意味着在您进行搜索时,它会在您搜索时为您找到所有可用的结果。如果在您进行搜索时有新记录,它们将不会被包括在内。
    【解决方案4】:

    我知道这已经过时了,但我遇到了同样的困境,我宁愿大声思考。

    在该提要中,您似乎对每个请求的相关文档越来越不关心。我不是故意说时间戳/评论计数等,就 ES 而言,您谈论的是可以通过多种因素计算的分数,而您想要的是继续沿着该评分之路搜索。

    我想到的解决方案是:如果您还关心更多相关文档(例如 Facebook 在顶部显示“可用的 X 个新故事”),您可以先从头开始搜索,直到找到您遇到的第一个文档(以前最相关的那个),并且通过将之前的文档数添加到您已经在提要中显示的文档数中,您可以确定估计的偏移量(您可能会在竞争条件下得到一些重复,只需删除它们) .

    所以你真正需要做的是搜索顶部直到你到达第一个文档,然后搜索估计的底部并删除所有比最后一个文档更相关的内容。

    这都是假设大量的提要永远不会改变,如果文档 Y 在 X 和 Z 之间,它将永远保持在那里。

    如果分数是恒定的(这不太可能,因为这意味着它总是会因为提要不断变化而上升),您还可以按最后一个文档的分数以下的所有内容进行过滤。

    【讨论】:

      猜你喜欢
      • 2021-12-06
      • 2021-05-18
      • 2018-09-03
      • 1970-01-01
      • 2020-08-06
      • 2020-12-04
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多