2012-09-28 20 views
6

Zbudowałem indeks książek Lucene.net. Wszystko działa dobrze, ale muszę dodać inny sposób zapytania do indeksu i nie mogę wymyślić, jak to zrobić.Lucene.Net większy niż/mniej niż TermRangeQuery?

Zasadniczo każda książka ma przedział wiekowy, do którego nadaje się. Jest to wyrażone przez dwie kolumny mianowicie - minAge i maxAge. Obie kolumny są liczbami całkowitymi.

jestem indeksowania i przechowywania tych pól w poniższej pętli

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

Jak widać jestem dopełnienie się pola minAge i maxAge jak myślałem byłoby najłatwiej uruchomić TermRangeQuery przeciwko niemu.

Jednak muszę zapytać obie kolumny minAge i maxAge z Ery aby sprawdzić, czy spada z Wiek w przedziale wiekowym określonym przez minAge i maxAge.

SQL byłoby

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

Niestety nie widzę sposobu, aby to zrobić. Czy to jest możliwe w Lucene.Net?

Odpowiedz

10

Powinieneś być w stanie to zrobić wykorzystując zapytania o zakres, jeśli pamięć jest obsługiwana. To skutecznie odwrotność standardowego zapytania zasięgu, ale powinien być w stanie, coś jak:

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

Lub, jeśli buduje obiekty Query RangeQuery (albo jeszcze lepiej, NumericRangeQuery) albo z górną lub dolna granica zerowa działa jako zakres otwarty.

Użyłem składni powyżej wcześniej, ale wsparcie wydaje się być nieco ... chwiejny na nim. Jeśli to nie pomoże, zawsze można po prostu ustawić odpowiednio niska dolna granica (0) i wysoka górna granica (powiedzmy, 1000), takie jak:

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

które powinny być na tyle bezpieczny, wyjąwszy żadnej Matuzalemów.

+0

Marvelous wykorzystywane twojej rady i to pracowała doskonale. Skończyło się rozwiązanie do wyszukiwania, które opiszę poniżej. – wingyip

4

Skończyło się to zrobić za pomocą odpowiedź femtoRgon jest powyżej.

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

Skrzydło

Powiązane problemy