我在 .NET 中对 lucene.net 索引进行排序时遇到问题。我尝试了 stackoverflow 上的几乎所有解决方案并寻找谷歌答案。我正在使用 Lucene.NET 2.9.2 和 ASP.NET 2.0。我想像在 sql 中一样对字符串进行排序,您可以输入“order by Title desc [asc]”
我将向您展示我的代码,希望有人可以帮助我。
//Here I create Index with some fields
doc.Add(new Field("prod_id",row["prod_id"].ToString(),Field.Store.YES,Field.Index.ANALYZED));
doc.Add(new Field("prod_title", row["prod_title"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("prod_desc", row["prod_desc"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("prod_author", row["prod_author"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("prod_publisher", row["prod_publisher"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("prod_price", row["prod_price"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
//Then next I try to do search with sort option:
//method for return approciate Sort object
private static Sort SetSortForLucene(string _sort)
{
Sort sort;
switch (_sort)
{
case "UnitPriceGorss":
sort = new Sort(new SortField("prod_price",SortField.DOUBLE,false);
break;
case "UnitPriceGorssDESC":
sort = new Sort(new SortField("prod_price",SortField.DOUBLE,true);
break;
case "Title":
//not working
sort = new Sort(new SortField("prod_title", SortField.STRING, true));
break;
case "TitleDESC":
//not working
sort = new Sort(new SortField("prod_title", SortField.STRING, false));
break;
case "":
sort = new Sort(new SortField("prod_title", SortField.STRING, false));
break;
default:
sort = new Sort(new SortField("prod_title", SortField.STRING, false));
break;
}
return sort;
}
//Inside my query of lucene method:
StandardAnalyzer analizer = new StandardAnalyzer(Version.LUCENE_29);
IndexReader reader =IndexReader.Open(IndexPath);
Searcher searcher = new IndexSearcher(reader);
//Here call for Sort object
Sort sort = SetSortForLucene(_sort);
TopFieldDocCollector collector = new TopFieldDocCollector(reader, sort, pageSize);
//Find which document field need to me asked in QueryParser object
string _luceneField = "";
if (luceneField.Contains("_"))
_luceneField = luceneField;
else
switch (luceneField)
{
case "Title": _luceneField = "prod_title"; break;
case "Description": _luceneField = "prod_desc"; break;
case "Author": _luceneField = "prod_author"; break;
case "Publisher": _luceneField = "prod_publisher"; break;
default: _luceneField = "prod_title"; break;
}
QueryParser parser = new QueryParser(_luceneField, analizer);
Query query = parser.Parse(luceneQuery);
ScoreDoc[] hits;
searcher.Search(query,collector);
//Obtaining top records from search but without any sort.
hits = collector.TopDocs().scoreDocs;
foreach (ScoreDoc hit in hits)
{
Document doc = searcher.Doc(hit.doc);
string a = doc.Get("prod_id");
int id = 0;
if (hit.score > score)
{
if (int.TryParse(doc.Get("prod_id"), out id))
tmpId.Add(id);
}
}
//I also define stop words for full text searching and i think this is
//real cause of problem with sorting.
System.String[] stopWords = new System.String[]{"a","że","w","przy","o","bo","co","z","za","ze","ta","i","no","do"};
我用过这个stackoverflow 中的链接。 https://stackoverflow.com/questions/3990760/random-sorting-results-in-lucene-net-2-4
and 这个漂亮的链接 http://www.logiclabz.com/c/search-lucene-index-in-net-c-with-sorting-options.aspx解决我的问题,但排序失败,我不知道我的代码出了什么问题。
几天后我终于找到了解决方案。我想要排序的字段在表示字符串值时不应被标记化。
例如,当我想按标题(升序/降序)对产品进行排序时,您应该输入如下内容:
doc.Add(new Field(Product.PROD_TITLE_SORT, row["prod_title"].ToString().Replace(" ", "_") + "_" + row[Product.PROD_ID].ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED));
我不明白的是为什么这个字段不存储也不分析,因此 lucene.net 可以按这个添加的字段进行排序。这个排序字段甚至不在索引中!我用 lukeall-1.0.1.jar 索引浏览器检查过。
其次,您需要创建适当的排序方法:
private static Sort SetSortForLucene(string _sort)
{
Sort sort;
_sort = !string.IsNullOrEmpty(_sort) ? _sort : "";
switch (_sort)
{
case "UnitPriceGorss":
sort = new Sort(new SortField(PROD_PRICE, SortField.DOUBLE, false));
break;
case "UnitPriceGorssDESC":
sort = new Sort(new SortField(PROD_PRICE, SortField.DOUBLE, true));
break;
case "Title":
//not it works perfectly.
sort = new Sort(new SortField(PROD_TITLE_SORT, SortField.STRING, true));
break;
case "TitleDESC":
//not it works perfectly.
sort = new Sort(new SortField(PROD_TITLE_SORT, SortField.STRING, false));
break;
case ""://Here is default sorting behavior. It get's result according to Lucene.NET search result score.
sort = new Sort(SortField.FIELD_SCORE);
break;
default:
sort = new Sort(SortField.FIELD_SCORE);
break;
}
return sort;
}
让我真正怀疑的是,当字段在 lucene 全文索引中建立索引时,排序可以与 SortField.DOUBLE 一起使用。
我希望这篇文章能够帮助任何有类似排序问题的人。