如何使用 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 管理“分页”?的主要内容,如果未能解决你的问题,请参考以下文章