2010-12-30 37 views
7

Tôi đã có người tìm kiếm của tôi làm việc thực sự tốt, tuy nhiên nó có xu hướng trả về kết quả đã lỗi thời. Trang web của tôi giống NerdDinner theo đó các sự kiện trong quá khứ trở nên không liên quan.Lucene.Net: Làm cách nào để thêm bộ lọc ngày vào kết quả tìm kiếm của tôi?

tôi đang lập chỉ mục như
ghi chú này: ví dụ của tôi là trong VB.NET, nhưng tôi không quan tâm nếu ví dụ được đưa ra trong 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 

Chú ý làm thế nào tôi có một " ngày "chỉ mục lưu trữ ngày sự kiện.

tìm kiếm của tôi sau đó trông như thế này

''# 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 

tôi đã thử những điều sau đây, nhưng nó đã không có kết quả (ném một 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 

Tôi cũng tìm thấy các tài liệu sau đây, nhưng tôi không thể làm cho người đứng đầu hoặc đuôi của nó
http://lucene.apache.org/java/1_4_3/api/org/apache/lucene/search/DateFilter.html

+0

Ok, tôi nghĩ bạn đã thêm lại mvc. Vì vậy, ok của bạn với một ví dụ IronPython hoặc IronRuby? ;) – jfar

+0

:-p [uh đó là prolly đẩy nó] –

Trả lời

9

bạn đang liên kết đến các tài liệu api của Lucene 1.4.3 . Lucene.Net hiện tại là 2.9.2. Tôi nghĩ rằng một nâng cấp là do.

Trước tiên, bạn đang sử dụng Store.Yes rất nhiều. Các trường được lưu trữ sẽ làm cho chỉ mục của bạn lớn hơn, có thể là vấn đề về hiệu suất. Vấn đề ngày tháng của bạn có thể dễ dàng được giải quyết bằng cách lưu trữ ngày tháng dưới dạng chuỗi theo định dạng "yyyyMMddHHmmssfff" (độ phân giải thực sự cao, xuống đến mili giây). Bạn có thể muốn giảm độ phân giải để tạo ít thẻ hơn để giảm kích thước chỉ mục của mình.

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

Sau đó, bạn áp dụng bộ lọc cho tìm kiếm của mình (thông số thứ hai, nơi bạn hiện đang chuyển vào Không có gì/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); 

Bạn có thể làm điều này bằng cách sử dụng BooleanQuery kết hợp truy vấn bình thường của bạn với một RangeQuery, nhưng điều đó cũng sẽ ảnh hưởng đến ghi (được tính trên các truy vấn, không phải là bộ lọc). Bạn cũng có thể muốn tránh sửa đổi truy vấn để đơn giản, vì vậy bạn biết truy vấn nào được thực hiện.

+0

ví dụ chỉ là những gì tôi tìm thấy làm một tìm kiếm của Google. Tôi đang sử dụng Lucene.Net v2.4.0.2 –

+0

Tôi muốn người dùng có thể tìm kiếm thông qua 'ngày: dd/mm/yyyy' sẽ vẫn hoạt động được không? –

+0

Tìm kiếm nhanh trong Changes.txt huyền diệu chỉ ra rằng 2.4.0 đã được phát hành 2008-10-06, và là sau khi dòng 1100 trong một danh sách dài các bản sửa lỗi và các tính năng mới. Tôi đoán có một định dạng chỉ mục mới (mà bạn sẽ được tự động nâng cấp lên, nhưng phiên bản cũ hơn không thể tiếp tục đọc), nhưng vẫn còn, bạn nên xem xét nâng cấp. – sisve

7

Bạn có thể kết hợp nhiều truy vấn với một BooleanQuery. Vì Lucene chỉ tìm kiếm ghi chú văn bản rằng trường ngày trong chỉ mục của bạn phải được sắp xếp theo thứ tự quan trọng nhất cho phần ít quan trọng nhất của ngày, tức là ở định dạng IS8601 ("2010-11-02T20: 49: 16.000000 + 00: 00")

Ví dụ:

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

Ngoài ra nếu một ký tự đại diện là không đủ chính xác bạn có thể thêm một RangeQuery thay vì:

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

oh crap, làm thế nào tôi phải tìm ra cách để làm một tìm kiếm boolean ;-) –

Các vấn đề liên quan