2012-09-28 19 views
6

Tôi đã xây dựng một chỉ mục Lucene.net của sách. Tất cả đều hoạt động tốt nhưng tôi cần phải thêm một cách khác để truy vấn chỉ mục và tôi không thể tìm ra cách thực hiện.Lucene.Net lớn hơn/ít hơn so với TermRangeQuery?

Về cơ bản, mỗi sách đều có độ tuổi phù hợp. Điều này được thể hiện bằng hai cột cụ thể là - minAge và maxAge. Cả hai cột đều là số nguyên.

Tôi đang lập chỉ mục và lưu trữ các trường này trong vòng lặp sau

foreach (var catalogueBook in books) 
{ 
    var book = new Book(catalogueBook.CatalogueBookNo,catalogueBook.IssueId); 

    var strTitle = book.FullTitle ?? ""; 
    var strAuthor = book.Author ?? ""; 
    // create a Lucene document for this book 
    var doc = new Document(); 

    // add the ID as stored but not indexed field, not used to query on 
    doc.Add(
     new Field(
      "BookId", 
      book.CatalogueBookNo.ToString(System.Globalization.CultureInfo.InvariantCulture), 
      Field.Store.YES, 
      Field.Index.NOT_ANALYZED_NO_NORMS, 
      Field.TermVector.NO)); 

    // add the title and author as stored and tokenized fields, the analyzer processes the content 
    doc.Add(
     new Field("FullTitle", 
      strTitle.Trim().ToLower(), 
      Field.Store.YES, 
      Field.Index.ANALYZED, 
      Field.TermVector.NO)); 

    doc.Add(
     new Field("Author", 
      strAuthor.Trim().ToLower(), 
      Field.Store.YES, 
      Field.Index.ANALYZED, 
      Field.TermVector.NO)); 

    doc.Add(
     new Field("IssueId", 
      book.IssueId, 
      Field.Store.YES, 
      Field.Index.NOT_ANALYZED_NO_NORMS, 
      Field.TermVector.NO)); 

    doc.Add(
     new Field(
      "PublicationId", 
      book.PublicationId.Trim().ToLower(), 
      Field.Store.YES, 
      Field.Index.NOT_ANALYZED_NO_NORMS, 
      Field.TermVector.NO)); 

    doc.Add(
     new Field(
      "MinAge", 
      book.MinAge.ToString("0000"), 
      Field.Store.YES, 
      Field.Index.NOT_ANALYZED_NO_NORMS, 
      Field.TermVector.NO)); 

    doc.Add(
     new Field(
      "MaxAge", 
      book.MaxAge.ToString("0000"), 
      Field.Store.YES, 
      Field.Index.NOT_ANALYZED_NO_NORMS, 
      Field.TermVector.NO)); 

    doc.Add(new NumericField("Price",Field.Store.YES,true).SetDoubleValue(Convert.ToDouble(book.Price))); 

    //Now we can loop through categories 
    foreach(var bc in book.GetBookCategories()) 
    { 
     doc.Add(
      new Field("CategoryId", 
       bc.CategoryId.Trim().ToLower(), 
       Field.Store.YES, 
       Field.Index.NOT_ANALYZED_NO_NORMS, 
       Field.TermVector.NO)); 
    } 

    // add the document to the index 
    indexWriter.AddDocument(doc); 
} 

// make lucene fast 
indexWriter.Optimize(); 
} 

Như bạn có thể thấy tôi đang đệm ra các lĩnh vực minAge và maxAge như tôi nghĩ rằng nó sẽ là đơn giản nhất để chạy một TermRangeQuery chống lại nó.

Tuy nhiên, tôi cần phải truy vấn cả hai cột minAge và maxAge có Độ tuổi để xem Tuổi đó có nằm trong phạm vi Độ tuổi được xác định bởi minAge và maxAge hay không.

Sql sẽ

Select * 
From books 
where @age >= minAge and @age <= maxAge 

Đáng tiếc là tôi không thể nhìn thấy một cách để làm điều này. Điều này thậm chí có thể có trong Lucene.Net không?

Trả lời

10

Bạn có thể thực hiện việc này bằng cách sử dụng các truy vấn phạm vi nếu bộ nhớ phân phát. Đây là một cách hiệu quả nghịch đảo của một truy vấn phạm vi tiêu chuẩn, nhưng bạn sẽ có thể, một cái gì đó như:

+minAge:[* TO @age] +maxAge:[@age TO *] 

Hoặc, nếu bạn xây dựng các đối tượng truy vấn, một RangeQuery (hoặc tốt hơn chưa, NumericRangeQuery) với một trong hai phía trên hoặc null bị ràng buộc thấp hơn hoạt động như một phạm vi mở kết thúc.

Tôi đã sử dụng cú pháp ở trên trước đây, nhưng hỗ trợ có vẻ hơi ... run rẩy trên đó. Nếu điều đó không làm việc, bạn luôn có thể chỉ cần đặt một cách đầy đủ thấp thấp hơn giới hạn (0) và cao trên ràng buộc (ví dụ 1000), chẳng hạn như:

+minAge:[0000 TO @age] +maxAge:[@age TO 1000] 

nào nên được an toàn đủ, trừ đi Methuselahs.

+0

Marvelous sử dụng lời khuyên của bạn và nó làm việc một điều trị. Đã kết thúc với giải pháp tìm kiếm mà tôi sẽ phác thảo bên dưới. – wingyip

4

Đã kết thúc thực hiện việc này với sự trợ giúp của câu trả lời của femtoRgon ở trên.

var q = new TermRangeQuery("MinAge", "0000",searchTerms.Age.ToString("0000"), true, true); 
mainQuery.Add(q, BooleanClause.Occur.MUST); 
q = new TermRangeQuery("MaxAge", searchTerms.Age.ToString("0000"),"9999", true, true); 
mainQuery.Add(q, BooleanClause.Occur.MUST); 

Wing