2010-12-30 24 views
7

私の検索人は本当にうまく働いていますが、時代遅れの結果を返す傾向があります。私のサイトはNerdDinnerによく似ていて、過去の出来事は無関係になっています。Lucene.Net:検索結果に日付フィルタを追加するにはどうすればよいですか?

私は現在、この
ノートのようにインデックスを作成しています:例はC#で

Public Function AddIndex(ByVal searchableEvent As [Event]) As Boolean Implements ILuceneService.AddIndex 

     Dim writer As New IndexWriter(luceneDirectory, New StandardAnalyzer(), False) 

     Dim doc As Document = New Document 

     doc.Add(New Field("id", searchableEvent.ID, Field.Store.YES, Field.Index.UN_TOKENIZED)) 
     doc.Add(New Field("fullText", FullTextBuilder(searchableEvent), Field.Store.YES, Field.Index.TOKENIZED)) 
     doc.Add(New Field("user", If(searchableEvent.User.UserName = Nothing, 
            "User" & searchableEvent.User.ID, 
            searchableEvent.User.UserName), 
           Field.Store.YES, 
           Field.Index.TOKENIZED)) 
     doc.Add(New Field("title", searchableEvent.Title, Field.Store.YES, Field.Index.TOKENIZED)) 
     doc.Add(New Field("location", searchableEvent.Location.Name, Field.Store.YES, Field.Index.TOKENIZED)) 
     doc.Add(New Field("date", searchableEvent.EventDate, Field.Store.YES, Field.Index.UN_TOKENIZED)) 

     writer.AddDocument(doc) 

     writer.Optimize() 
     writer.Close() 
     Return True 

    End Function 

お知らせを与えられている場合は、私の例では、VB.NETであるが、私は気にしない私が持っていますか」イベントの日付を格納する「日付」インデックスです。

は私の検索では、私は次のことをしようとしました。この

''# code omitted 
     Dim reader As IndexReader = IndexReader.Open(luceneDirectory) 
     Dim searcher As IndexSearcher = New IndexSearcher(reader) 
     Dim parser As QueryParser = New QueryParser("fullText", New StandardAnalyzer()) 
     Dim query As Query = parser.Parse(q.ToLower) 

     ''# We're using 10,000 as the maximum number of results to return 
     ''# because I have a feeling that we'll never reach that full amount 
     ''# anyways. And if we do, who in their right mind is going to page 
     ''# through all of the results? 
     Dim topDocs As TopDocs = searcher.Search(query, Nothing, 10000) 
     Dim doc As Document = Nothing 

     ''# loop through the topDocs and grab the appropriate 10 results based 
     ''# on the submitted page number 
     While i <= last AndAlso i < topDocs.totalHits 
       doc = searcher.Doc(topDocs.scoreDocs(i).doc) 
       IDList.Add(doc.[Get]("id")) 
       i += 1 
     End While 
''# code omitted 

のように見えますが、それは(とNullReferenceExceptionを投げた)無駄にしました。

 While i <= last AndAlso i < topDocs.totalHits 
      If Date.Parse(doc.[Get]("date")) >= Date.Today Then 
       doc = searcher.Doc(topDocs.scoreDocs(i).doc) 
       IDList.Add(doc.[Get]("id")) 
       i += 1 
      End If 
     End While 

私はまた、次のドキュメントを見つけましたが、私はそれの頭や尾
http://lucene.apache.org/java/1_4_3/api/org/apache/lucene/search/DateFilter.html

+0

私はあなたがmvcを追加したと思いました。だからIronPythonやIronRubyの例であなたの大丈夫? ;) – jfar

+0

:-p [それはprollyそれを押している] –

答えて

9

あなたはLuceneの1.4.3のAPIドキュメントにリンクしています。 Lucene.Netは現在2.9.2です。私はアップグレードが必要だと思う。

まず、Store.Yesを使用しています。保存されたフィールドはインデックスを大きくします。これはパフォーマンス上の問題です。あなたの日付の問題は、 "yyyyMMddHHmmssfff"という形式の文字列として日付を格納することで簡単に解決できます(これはミリ秒までの高解像度です)。解決策を減らして、より少ないトークンを作成して、索引サイズを減らすことができます。

var dateValue = DateTools.DateToString(searchableEvent.EventDate, DateTools.Resolution.MILLISECOND); 
doc.Add(new Field("date", dateValue, Field.Store.YES, Field.Index.NOT_ANALYZED)); 

次に、検索にフィルタを適用します(2番目のパラメータは、現在Nothing/nullを渡しています)。

var dateValue = DateTools.DateToString(DateTime.Now, DateTools.Resolution.MILLISECOND); 
var filter = FieldCacheRangeFilter.NewStringRange("date", 
       lowerVal: dateValue, includeLower: true, 
       upperVal: null, includeUpper: false); 
var topDocs = searcher.Search(query, filter, 10000); 

あなたはRangeQueryで通常のクエリを組み合わせBooleanQueryを使用してこれを行うことができ、それはまた、(クエリではなく、フィルタに基づいて計算される)得点影響を及ぼすことになります。簡単にするためにクエリを変更しないようにすることで、実行されるクエリが分かるようにすることもできます。

+0

例はちょうど私がGoogleの検索を行ったことがわかった。私はLucene.Net v2.4.0.2を使用しています –

+0

私は 'date:dd/mm/yyyy'で検索できるようにしますか?これはまだ動作しますか? –

+0

魔法のChanges.txtのクイック検索では、2.4。0は2008年10月6日にリリースされ、バグ修正と新機能の長いリストで1100行目以降のものです。私は新しいインデックスフォーマット(あなたは自動的にアップグレードされますが、古いバージョンは読むことができません)がありますが、まだアップグレードを考慮する必要があります。 – sisve

7

をすることはできませんあなたはBooleanQueryで複数のクエリを組み合わせることができます。 Luceneはテキストのみを検索するので、インデックスの日付フィールドは日付の最も重要な部分、つまりIS8601形式( "2010-11-02T20:49:16.000000 + 00:00")で並べ替える必要があります

例:

Lucene.Net.Index.Term searchTerm = new Lucene.Net.Index.Term("fullText", searchTerms); 
Lucene.Net.Index.Term dateRange = new Lucene.Net.Index.Term("date", "2010*"); 

Lucene.Net.Search.Query termQuery = new Lucene.Net.Search.TermQuery(searchTerm); 
Lucene.Net.Search.Query dateRangeQuery = new Lucene.Net.Search.WildcardQuery(dateRange); 

Lucene.Net.Search.BooleanQuery query = new Lucene.Net.Search.BooleanQuery(); 
query.Add(termQuery, BooleanClause.Occur.MUST); 
query.Add(dateRangeQuery, BooleanClause.Occur.MUST); 

代わりにワイルドカードがあなたの代わりにRangeQueryを追加することができます十分に正確ではない場合:

Lucene.Net.Search.Query termQuery = new Lucene.Net.Search.TermQuery(searchTerm); 
Lucene.Net.Index.Term date1 = new Lucene.Net.Index.Term("date", "2010-11-02*"); 
Lucene.Net.Index.Term date2 = new Lucene.Net.Index.Term("date", "2010-11-03*"); 
Lucene.Net.Search.Query dateRangeQuery = new Lucene.Net.Search.RangeQuery(date1, date2, true); 

Lucene.Net.Search.BooleanQuery query = new Lucene.Net.Search.BooleanQuery(); 
query.Add(termQuery, BooleanClause.Occur.MUST); 
query.Add(dateRangeQuery, BooleanClause.Occur.MUST); 
+0

ああ、私はブーリアン検索を行う方法を理解する必要があります;-) –