如何使用 Solr 管理“分页”?

Posted

技术标签:

【中文标题】如何使用 Solr 管理“分页”?【英文标题】:How to manage "paging" with Solr? 【发布时间】:2011-01-21 19:54:47 【问题描述】:

我有一个分类网站... 我让 Solr 进行分类搜索,然后返回 ID:nrs,然后我用它来放入数组中。然后我使用这个数组在 mysql 数据库中查找 ID:s 与 Solr 返回的数组中的 ID:s 匹配的任何分类。

现在,因为这个数组可能非常大(10 万条记录或更多),所以我需要“分页”结果,以便一次返回 100 个。然后在 MySql 中使用这 100 个 ID:s 来查找分类。

那么,是否可以使用 SOLR 进行分页?

如果是这样,怎么办?我需要示例代码...请问结果是什么。

主要是我需要一个完整的例子!

谢谢

【问题讨论】:

【参考方案1】:

使用start 和rows 参数管理分页,例如:

?q=something&rows=10&start=20

会给你 10 个文档,从文档 20 开始。

关于从 MySQL 获取其他信息,您只能靠自己了。我和其他人 already suggested to you 将所有内容存储在 Solr 中,以避免对 MySQL 的额外查询。

【讨论】:

我不会投反对票,但如果需要任何类型的事务访问,使用 solr 作为主数据存储可能是一个糟糕的选择。 Solr 是一个搜索服务器...将所有数据放在那里以供搜索和查看是有意义的,但这并不意味着没有交易数据必须来自和进入数据库。 @Zak:你为什么认为他需要事务访问?如果使用得当,Solr 可以作为许多应用程序的主数据存储正常工作。像往常一样,为工作使用正确的工具。 @Mauricioscheffer:我们尝试过从 solr 存储/检索所有内容的路径。但是,在像这样的深度分页示例的情况下,solr 开始返回重复的结果,或者有时不会返回所有内容。所以需要一个“排序”参数。然而,一旦我们添加了 'sort' 参数,我们就开始遇到堆空间问题(出于某种原因,在 1GB 中对 75k 个文档(每个 @PrashantSaraswat cursorMark 将在 Solr 4.7 中可用 issues.apache.org/jira/browse/SOLR-5463 当前稳定版本是 4.6.1,所以我猜它将在未来几个月内发布。【参考方案2】:

可能是一个有点老的问题和许多有用的答案和建议,但我会尝试总结结果并描述使用 cursor 对大型数据集进行分页的解决方案,bec。我最近遇到了这个问题。

作为mentioned by Yonik,通常start/rows 的问题是,当我们有大数据集并且start 比零更远(更远)时,我们有很好的在效率和内存方面的开销。这是因为从500K条记录的“中间”提取20个文档+使用排序,至少需要对所有数据集进行排序(内部唯一性排序 em>)。此外,如果搜索是分布式的,它将更加消耗资源,bec。来自每个分片的数据集(500 020 行)应返回到要合并的聚合器节点,以找出适用的 20 行。

Solr 无法计算哪个匹配文档是排序顺序中的第 999001 个结果,除非先确定前 999000 个匹配的排序结果是什么。


这里的解决方案是使用Solr cursorMark

在第一个查询中,您宣布 &cursorMark=*.意思是下一步:

你可以认为这类似于 start=0 来告诉 Solr“从我的排序结果的开头开始”,除了它还通知 Solr 你想使用光标.

! 这里的一个“警告”是您的sort 子句必须包含 uniqueKey 字段。如果它是唯一的,它可以是id 字段。

第一个查询的一部分如下所示:

?sort=price desc,id asc&start=0&cursorMark=* ...

结果你会收到下一个结构


    "response":"numFound":20,"start":0,"docs":[ /* docs here */ ],
    "nextCursorMark":"AoIIRPoAAFBX" // Here is cursor mark for next "page"

要检索下一页,下一个查询将查找下一个:

?sort=price desc,id asc&start=0&cursorMark=AoIIRPoAAFBX ...

请注意之前回复中的cursorMark。结果,您将获得下一页结果(与第一个响应的结构相同,但具有另一个 nextCursorMarker)。等等……

这种方法非常适合无限滚动分页,但要在经典分页中使用它,需要考虑一些事情:)。

这里有一些我找到的解决这个问题的参考资料,希望它可以帮助某人完成它。

Pagination of results Sorting, Paging, and Deep Paging in Solr(Yonik's 材料)(非常感谢!) Efficient Cursor Based Iteration of Large Result Sets

【讨论】:

cursorMark 是否仍然是获取大型分页数据的最佳方式,还是我们有任何其他最新技术。 @yallam 使用游标分页有点特殊。原因是我们不能事先跳转到例如第 10/55 页 bec。无论常规分页是否假定我们可以随时跳转到任何页面,我们都没有指向此范围的指针。而 cursor 需要前一个指针 来获取下一个指针,它适用于无限滚动的情况。另外我不知道这个comment of Prashant Saraswat 是否仍然相关,但也很高兴知道。【参考方案3】:

看看IBM。也许这会让你走上正确的道路。

结果数:指定要返回的最大结果数。

开始:在结果集中开始的偏移量。这对分页很有用。

所以你可能想要一些变化

<str name="rows">10</str>
<str name="start">0</str>

您的 solr 客户端应该提供一些方法来轻松获得结果总数。

【讨论】:

如果您正在执行一些深度分页,您可能需要检查 Solr cursors 以获得更好的性能(它们不像 sql 游标那样邪恶!:)【参考方案4】:

“start”参数控制搜索结果的偏移量,“rows”参数控制从那里返回多少文档。

如果您正在执行“深度分页”(迭代许多页面),那么使用游标迭代结果集可以获得更好的性能。

【讨论】:

【参考方案5】:

我认为值得一提的是,solr 会与当前页面结果一起返回找到的记录总数。

例如调用:

http://192.168.0.1:8983/solr/select?qt=edismax&fl=*,score&qf=content^2%20metatag.description^3%20title^5%20metatag.keywords^10&q=something&start=20&rows=10&wt=xml&version=2.2

回复是:

<response>
    <lst name="responseHeader">
        <int name="status">0</int>
        <int name="QTime">1</int>
        <lst name="params">
            <str name="fl">*,score</str>
            <str name="q">something</str>
            <str name="qf">content^2 metatag.description^3 title^5 metatag.keywords^10</str>
            <str name="qt">edismax</str>
            <str name="wt">xml</str>
            <str name="rows">10</str>
            <str name="version">2.2</str>
            </lst>
        </lst>
        <result name="response" numFound="1801" start="0" maxScore="0.15953878">
            <doc>...</doc>
            <doc>...</doc>
            <doc>...</doc>
...

使用 solrj,方法查询返回具有以下方法的 SolrDocumentList: getNumFound()。

【讨论】:

以上是关于如何使用 Solr 管理“分页”?的主要内容,如果未能解决你的问题,请参考以下文章

solr使用cursorMark做深度分页

Solr中使用游标进行深度分页查询以提高效率(适用的场景下)

如何在 solr 6+ 中使用托管模式编辑字段类型

mysql分库 分页查询

如何自动启动 Solr?

Solr UI Admin管理界面使用说明