2010-12-30 2 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 

은 또한 다음과 같은 문서를 발견,하지만 당신은 BooleanQuery 여러 쿼리를 결합 할 수 있습니다 그것은
http://lucene.apache.org/java/1_4_3/api/org/apache/lucene/search/DateFilter.html

+0

좋아, 나는 당신이 mvc를 다시 추가했다고 생각했다. 그래서 IronPython 또는 IronRuby 예제로 확인해 주시겠습니까? ;) – jfar

+0

:-) [prolly 그것을 추진하고있다] –

답변

9

. 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)); 

그런 다음 검색에 필터를 적용합니다 (두 번째 매개 변수는 현재 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

의 머리 또는 꼬리를 만들 수 없습니다. 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 대신 : 당신은 루씬 1.4.3의 API 문서에 연결하고

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

오, 쓰레기 검색을 수행하는 방법을 알아 내야 만합니다. ;-) –

관련 문제