Lucene聚類分組統計功能(grouping)

在搜索的項目中,我們經常有對搜索結果進行分組或對字段進行壓縮的需求。之前的文章提到這個功能已經添加到solr中併成爲用戶一個非常需要的特性。最近結果分組被作爲一個擴展包加入到lucene3.1中,而在4.0中將直接作爲一個模塊。添加這個功能到lucene中使用起來將會更靈活。目前正在努力將結果分組放入到solr的3.X版本分支中。具體參考SOLR-2524這意味着在solr3.2中我們將可以使用這個功能了!

歷史
這個功能起於4年前,分支SOLR-236被創建的時候。那時結果分組關注於在結果集中對擁有相同字段值的文檔進行壓縮。隨着時間的推移,越來越多的人開始使用這個補丁。很多人提交了一些新的特性、調優。而字段的壓縮在Jira上作爲一個補丁起始於3年前,用戶需要對solr打補丁並運行在這個構建的版本上。這種明顯是一種錯誤的方式,以至於在這方面的問題發給了Solr的郵件組。另外,在Jira上有很多關於字段分組的補丁,這讓用戶很迷惑

去年9月結果分組在4.0-dev版中變的可用。字段壓縮功能也被重寫(SOLR-1682),並且性能也得到提升。另外,結果分組也被加入,所以這個特性有些小的改變。

最近,正嘗試着放入LUCENE-1421。這個Jira創建的目的是暴露結果分組的功能給lucene。在Solr主幹中,分組的代碼將會被重寫,並將分組模塊放入到lucene中。在3.x版本中,它已經被作爲一個擴展包了。目前還不能支持按方法(function)或查詢(query)進行分組。LUCENE-3099已經被創建,不久lucene就可以使用這些功能了。

Lucene的結果分組
Lucene中的分組很容易使用,參考下面的例子。類FirstPassGroupingCollector用來收集每組中有多少個文檔;SecondPassGroupingCollector收集有多少個分組。

FirstPassGroupingCollector c1 = new FirstPassGroupingCollector("author", groupSort, groupOffset + topNGroups);
indexSearcher.search(new TermQuery(new Term("content", searchTerm)), c1);
 
Collection<SearchGroup> topGroups = c1.getTopGroups(groupOffset, fillFields);
 
if (topGroups == null) {
   // No groups matched
  return;
}
 
boolean getScores = true;
boolean getMaxScores = true;
boolean fillFields = true;
SecondPassGroupingCollector c2 = new SecondPassGroupingCollector("author", topGroups, groupSort, docSort, docOffset + docsPerGroup, getScores, getMaxScores, fillFields);
    indexSearcher.search(new TermQuery(new Term("content", searchTerm)), c2);
 
TopGroups groupsResult = c2.getTopGroups(docOffset);


如果search的性能耗費大,則可以考慮使用CachingCollector。這個cache可以緩存第一次search時的文檔Id和評分,並提供給之後的查詢使用。使用方法請參考grouping documentation


有另一個收集器叫AllGroupsCollector,它可以收集查詢結果的所有組。下面的例子爲得到各個分組收集的總數量:
// First pass search has been executed
boolean getScores = true;
boolean getMaxScores = true;
boolean fillFields = true;
AllGroupsCollector c3 = new AllGroupsCollector("author");
SecondPassGroupingCollector c2 = new SecondPassGroupingCollector("author", topGroups, groupSort, docSort, docOffset + docsPerGroup, getScores, getMaxScores, fillFields);
indexSearcher.search(new TermQuery(new Term("content", searchTerm)), MultiCollector.wrap(c2, c3));
 
TopGroups groupsResult = c2.getTopGroups(docOffset);
groupsResult = new TopGroups(groupsResult, c3.getGroupCount());


通過MultiCollectorAllGroupsCollector能很好的封裝SecondPassGroupingCollectorAllGroupsCollector 也能獨立的在其他的收集器中使用。

結果分組在solr中的使用
現在Solr主幹上還沒有使用lucene 分組模塊;它使用它自己的分組模塊。Solr還沒有使用lucene的分組模塊的原因,是它還沒有對function和query的支持。然而Solr3.1還沒有實現分組的支持,用戶仍需要自己下分支然後編譯。更壞的是,很多用戶還在使用過時的補丁SOLR-236,這是我爲什麼創建SOLR-2524的原因.

SOLR-2524 分支涉及到集成lucene的擴展包到solr3.x分支中。這個版本也爲集成分組模塊的主幹版本到Solr4.0中作爲參考。Solr3.x的主幹分組將支持相同的響應格式和請求參數,具體描述請參見Solr FieldCollapse wiki page;它還不支持的功能還是function和query。

如果運行良好,這個分支將會提交到Solr3.2版本中,Solr的用戶就可以直接使用啦


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章