java - MongoDB + Solr performances

2022-09-01 21:20:48

我一直在四处寻找如何将MongoDB与Solr结合使用,这里的一些问题有部分回应,但没有真正具体的(更像是理论)。在我的应用程序中,我将在MongoDB中存储大量文档(可能高达数亿个),并且我想在这些文档的某些属性上实现全文搜索,所以我想Solr是最好的方法。

我想知道的是我应该如何配置/执行所有内容,以便它具有良好的性能?现在,这就是我所做的(我知道它不是最佳的):

1-在MongoDB中插入对象时,我将其添加到Solr中

SolrServer server = getServer();
SolrInputDocument document = new SolrInputDocument();
document.addField("id", documentId);
...
server.add(document);
server.commit();

2-更新对象的属性时,由于Solr不能只更新一个字段,因此首先我从MongoDB检索对象,然后使用对象和新属性更新Solr索引,并执行类似操作

StreamingUpdateSolrServer update = new StreamingUpdateSolrServer(url, 1, 0);
SolrInputDocument document = new SolrInputDocument();
document.addField("id", documentId);
...
update.add(document);
update.commit();

3-查询时,首先我查询Solr,然后在检索文档列表时,我浏览每个文档并:SolrDocumentList

  1. 获取文档的 ID
  2. 从MongoDB获取具有相同ID的对象,以便能够从那里检索属性

4-删除时,我还没有完成该部分,并且不确定如何在Java中执行此操作

因此,对于此处描述的每个方案,有没有人对如何以更有效的方式执行此操作提出建议?就像在Solr中拥有大量文档并一次添加一个文档时不需要1小时即可重建索引的过程一样?我在这里的要求是,用户可能希望一次添加一个文档,很多时候,我希望他们能够立即检索它


答案 1

你的方法实际上很好。一些流行的框架(如 Compass)正在执行您在较低级别描述的内容,以便自动镜像到通过 ORM 框架执行的索引更改(请参见 http://www.compass-project.org/overview.html)。

除了你描述的内容之外,我还会定期重新索引MongoDB中的所有数据,以确保Solr和Mongo都是同步的(可能不像你想象的那么长,这取决于文档的数量,字段的数量,每个字段的令牌数量以及分析器的性能: 我经常使用复杂的分析器在不到15分钟的时间内创建5到800万个文档(大约20个字段,但文本字段很短)的索引,只需确保您的RAM缓冲区不太小,并且在添加所有文档之前不要提交/优化)。

关于性能,提交成本高昂,优化成本高昂。根据对您最重要的内容,您可以在Solrconfig中更改mergefactor的值.xml(高值可以提高写入性能,而低值可以提高读取性能,10是一个很好的起始值)。

您似乎害怕索引构建时间。但是,由于 Lucene 索引存储是基于段的,因此写入吞吐量不应过多地依赖于索引的大小(http://lucene.apache.org/java/2_3_2/fileformats.html)。但是,预热时间会增加,因此应确保

  • 有典型的(特别是对于排序以加载字段缓存),但不是太复杂的查询在firstSearcher和newSearcher参数在你的solrconfig.xml配置文件,
  • useColdSearcher 设置为
    • false 以便具有良好的搜索性能,或者
    • 如果希望以较慢的搜索为代价更快地考虑对索引执行的更改,则为 true。

此外,如果数据在写入MongoDB后仅几X毫秒即可搜索,那么您可以使用UpdateHandler的conceptWithin功能。这样,Solr将不得不减少提交的频率。

有关 Solr 性能因素的更多信息,请参阅 http://wiki.apache.org/solr/SolrPerformanceFactors

若要删除文档,可以按文档 ID(如架构.xml中所定义)或查询删除:http://lucene.apache.org/solr/api/org/apache/solr/client/solrj/SolrServer.html


答案 2
  1. 您还可以等待更多文档,并仅每 X 分钟为它们编制索引。(当然,这在很大程度上取决于您的应用和要求)

  2. 如果您的文档很小,并且您不需要所有数据(存储在MongoDB中),则可以通过存储它们而不是索引来仅将所需的字段放在Solr文档中

<field name="nameoyourfield" type="stringOrAnyTypeYouuse"索引存储="false"="true"/>