更快地从Lucene Query获取不同值的方法

目前我喜欢这样:

IndexSearcher searcher = new IndexSearcher(lucenePath); Hits hits = searcher.Search(query); Document doc; List companyNames = new List(); for (int i = 0; i < hits.Length(); i++) { doc = hits.Doc(i); companyNames.Add(doc.Get("companyName")); } searcher.Close(); companyNames = companyNames.Distinct().Skip(offSet ?? 0).ToList(); return companyNames.Take(count??companyNames.Count()).ToList(); 

正如你所看到的,我首先收集所有字段(数千个),然后区分它们,可能会跳过一些并取出一些。

我觉得应该有更好的方法来做到这一点。

老实说,我不确定是不是因为Lucene没有提供“独特”的function。 我相信使用SOLR可以使用方面搜索来实现这一点,但如果你想在Lucene中使用它,你必须自己编写某种方面的function。 因此,只要您不遇到任何性能问题,就应该这样。

将这个问题与你之前的问题联系起来(重新:“太多条款”),我认为你绝对应该从索引阅读器中查看术语枚举。 缓存结果(我使用键入字段名称的排序字典,以及作为数据的术语列表,每个字段最多100个术语),直到索引阅读器变为无效并且离开。

或许我应该说,当遇到类似的问题时,我就是这么做的。

希望这可以帮助,

我建议你找一个跳过这种迭代的逻辑但是如果在你的上下文中没有解决方案那么你可以通过以下代码获得性能提升
1)在索引时,最好在第一个字段中放置要迭代的字段

 Document doc = new Document(); Field companyField = new Field(...); doc.Add(companyField); ... 

2)然后你需要像这样定义一个FieldSelector

 class CompanyNameFieldSelector : FieldSelector { public FieldSelectorResult Accept(string fieldName) { return (fieldName == "companyName" ? FieldSelectorResult.LOAD_AND_BREAK : FieldSelectorResult.NO_LOAD); } } 

3)然后,当你想迭代并选择这个字段时,你应该做这样的事情

 FieldSelector companySelector = new CompanyNameFieldSelector(); // when you iterate through your index doc = hits.Doc(i); doc.Get("companyName", companySelector); 

上面代码的性能比你提供的代码要好得多,因为它会跳过阅读不必要的文档字段,并节省时间。

 public List GetDistinctTermList(string fieldName) { List list = new List(); using (IndexReader reader = idxWriter.GetReader()) { TermEnum te = reader.Terms(new Term(fieldName)); if (te != null && te.Term != null && te.Term.Field == fieldName) { list.Add(te.Term.Text); while (te.Next()) { if (te.Term.Field != fieldName) break; list.Add(te.Term.Text); } } } return list; }