2010-01-13 20 views
8

Jak zrobić "LUB" w Lucene.NET. Zasadniczo posiadam tablicę identyfikatorów i chcę zwrócić wszystkie rekordy, w których dane pole zawiera którąkolwiek z wartości. Wcześniej robiłem to z jedną wartością, ale teraz chcę przekonwertować poniższy kod, aby MetaDataID był tablicą możliwych wartości zamiast jednej wartości.Lucene.NET "LUB"

if (MetaDataID.Length > 0) 
    completeQuery.Add(new QueryParser("MetaData", new StandardAnalyzer()).Parse(MetaDataID), BooleanClause.Occur.MUST); 

Odpowiedz

4

Trzeba użyć BooleanClause.Occur.SHOULD zamiast BooleanClause.Occur.MUST

np .:

BooleanQuery booleanQuery = new BooleanQuery(); 
Query query1 = new TermQuery(new Term("id", "<id 1>")); 
Query query2 = new TermQuery(new Term("id", "<id 2>")); 
booleanQuery.add(query1, BooleanClause.Occur.SHOULD); 
booleanQuery.add(query2, BooleanClause.Occur.SHOULD); 
+0

nie powoduje zwrotu zestawu A | B. Kiedy próbuję tego, otrzymuję wszystkie rekordy pasujące do innych klauzul MUST. To znaczy, że wygląda na to, że POWINIEN są ignorowane. – Kyle

+1

Nie jestem pewien, czy cię rozumiem. Ale myślę, że to, czego potrzebujesz, to zagnieździć twoje BooleanQueries. –

+0

"Musisz użyć bla ..." - ale dlaczego? –

2

Bądź ostrożny używając BooleanQuery do pobierania dokumentów przez id, ponieważ ma limit maksymalnych klauzul logicznych.

Podstawowa "LUB" klauzula w Lucene jest wykonywana tak, zakładając, że można przeszukiwać pola o nazwie "id":

"id: 1 ID: 2 ID: 3 ID: 4"

zamiast "AND" zapytanie:

"+ id: 1 + id: 2 + id: 3 + id: 4"

użyciu standardowego QueryParser i StringBuilder należy zrobić magię dla Ciebie.

3

Gdy naprawdę chcesz przeanalizować zapytanie, wystarczy wybrać poprawny analizator i format dla zapytania.

Narzędzie StandardAnalyzer nie jest dobrym wyborem podczas indeksowania czegokolwiek oprócz pełnego tekstu angielskiego, zwłaszcza w twoim przypadku! Odfiltrowuje liczby!

Najkrótszym rozwiązaniem w twoim przypadku jest stworzenie analizatora, który tokenizuje w separatorze i łączy twój obiekt w łańcuch.

Przykład:

Tworzenie Tokenizer który rozdziela w typowych separatory i analizatora, który używa go

using System.IO; 
using System.Linq; 
using Lucene.Net.Analysis; 

namespace Project.Analysis 
{ 
    public class TermTokenizer : LetterTokenizer 
    { 
     // some static separators 
     private static readonly char[] NONTOKEN_CHARS = new char[] { ',', ';', ' ', '\n', '\t' }; 

     protected override bool IsTokenChar(char c) 
     { 
      return !NONTOKEN_CHARS .Contains(c); 
     } 
    } 

    public class LowerCaseTermAnalyzer : Analyzer 
    { 
     public override TokenStream TokenStream(string fieldName, TextReader reader) 
     { 
      return new LowerCaseFilter(new TermTokenizer(reader)); 
     } 
    } 
} 

użyć nowego analizatora w parsera

(Ty należy dołączyć System.Linq)

if (MetaDataID.Length > 0) 
{ 
    // the search term will look like this: "1;5;7" 
    string searchTerm = string.Join(";", MetaDataID); 

    // the query parser uses the new Analyzer 
    QueryParser parser = new QueryParser("MetaData",new LowerCaseTermAnalyzer()); 

    // the parsed search term (only used internally) will look like this: 
    // "MetaData:1 MetaData:5 MetaData:7", which is essentially what you want to achieve 
    completeQuery.Add(new parser.Parse(MetaDataID), BooleanClause.Occur.MUST); 
} 
10

Łącząc zapytania Lucene, w których chcesz utworzyć rekord indeksu, który zawiera dowolną z wielu możliwych wartości z dodatkowymi kryteriami, które muszą zostać spełnione, utwórz wiele boolowskich obiektów zapytań.

Do pierwszej grupy „lub” warunków:

BooleanQuery booleanQueryInner = new BooleanQuery(); 
Query query1 = new TermQuery(new Term("id", "<id 1>")); 
Query query2 = new TermQuery(new Term("id", "<id 2>")); 
Query query3 = new TermQuery(new Term("id", "<id 3>")); 
Query query4 = new TermQuery(new Term("id", "<id 4>")); 
booleanQueryInner.add(query1, BooleanClause.Occur.SHOULD); 
booleanQueryInner.add(query2, BooleanClause.Occur.SHOULD); 
booleanQueryInner.add(query3, BooleanClause.Occur.SHOULD); 
booleanQueryInner.add(query4, BooleanClause.Occur.SHOULD); 

teraz łączyć z innymi warunków w zapytaniu

BooleanQuery booleanQueryOuter = new BooleanQuery(); 
booleanQueryOuter.add(booleanQueryInner, BooleanClause.Occur.MUST); 
booleanQueryOuter.add(boolenaQueryOtherConditions, BooleanClause.Occur.MUST); 

Teraz rejestry indeksowe będą zwracane tylko jeśli spełniają jeden z warunki w wewnętrznej grupie "OR", a także spełniają warunki w zapytaniu "inne warunki".

Powiązane problemy