2012-09-28 62 views
6

我已經建立了Lucene.net的書籍索引。所有工作都很好,但我需要添加另一種方式來查詢索引,我不知道如何去做。Lucene.Net大於/小於TermRangeQuery?

基本上每本書都有適合的年齡範圍。這由兩列表示 - minAge和maxAge。兩列都是整數。

我索引,並在下面的循環

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

存儲這些領域,你可以看到我填補了MINAGE和MAXAGE領域,我認爲這將是最簡單的針對它運行一個TermRangeQuery。

但是我需要使用Age來查詢minAge和maxAge列,以查看該Age是否屬於由minAge和maxAge定義的Age範圍。

的Sql將

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

可惜我不能明白的方式來做到這一點。這在Lucene.Net中甚至可能嗎?

回答

10

如果內存服務,您應該可以利用範圍查詢來做到這一點。這實際上是一個標準的範圍查詢的倒數,但你應該是可以的,是這樣的:

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

或者,如果你構建的查詢對象,一個RangeQuery(或更好,但NumericRangeQuery),同時按上或下限空作爲一個開放式的範圍。

我已經使用過上面的語法,但支持似乎有點...不穩定。如果不工作,你總是可以只設置一個足夠低的下限(0)和高上限(比如,1000),如:

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

這應該是足夠安全,禁止任何Methuselahs。

+0

奇妙的使用你的建議和它的工作一種享受。結束了我將在下面概述的搜索解決方案。 – wingyip

4

在上面femtoRgon的回答的幫助下完成了此操作。

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