Lucene: Multi-word frasi come termini di ricerca

Sto cercando di fare un motore di ricerca per telefono/locale commerciale directory utilizzando Apache Lucene.

Ho i campi per il nome della via, il nome dell’azienda, numero di telefono etc. Il problema che sto avendo è che quando provo a cercare per strada da cui il nome della strada ha più parole (ad esempio “la mezzaluna”), non vengono restituiti. Ma se provo a cercare con una sola parola, e.g “mezzaluna”, ottengo i risultati che voglio.

Sto indicizzazione i dati con le seguenti:

String LocationOfDirectory = "C:\\dir\\index";

StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_34);
Directory Index = new SimpleFSDirectory(LocationOfDirectory);

IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE.34, analyzer);
IndexWriter w = new IndexWriter(index, config);


Document doc = new Document();
doc.add(new Field("Street", "the crescent", Field.Store.YES, Field.Index.Analyzed);

w.add(doc);
w.close();

La mia ricerca di lavoro come questo:

int numberOfHits = 200;
String LocationOfDirectory = "C:\\dir\\index";
TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true);
Directory directory = new SimpleFSDirectory(new File(LocationOfDirectory));
IndexSearcher searcher = new IndexSearcher(IndexReader.open(directory);

WildcardQuery q = new WildcardQuery(new Term("Street", "the crescent");

searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;

Ho provato a scambiare il jolly query per una frase query, prima con l’intera stringa e poi dividere la stringa su lo spazio bianco e avvolgendoli in un BooleanQuery come questo:

String term = "the crescent";
BooleanQuery b = new BooleanQuery();
PhraseQuery p = new PhraseQuery();
String[] tokens = term.split(" ");
for(int i = 0 ; i < tokens.length ; ++i)
{
    p.add(new Term("Street", tokens[i]));
}
b.add(p, BooleanClause.Occur.MUST);

Tuttavia, questo non funziona. Ho provato ad utilizzare un KeywordAnalyzer invece di un StandardAnalyzer, ma poi tutti gli altri tipi di ricerca ha smesso di funzionare. Ho provato a sostituire gli spazi con gli altri personaggi (+ e @), e la conversione di query e da questo modulo, ma che ancora non funziona. Penso che non funziona perché + e @ sono caratteri speciali che non sono indicizzati, ma non riesco a trovare un elenco ovunque, di cui i personaggi sono così.

Sto iniziando ad andare un po ‘ folle, qualcuno sa di cosa sto facendo di sbagliato?

Grazie,
Rik

Carattere speciale può essere trovato qui: lucene.apache.org/core/3_5_0/queryparsersyntax.html#N10180.

OriginaleL’autore RikSaunderson | 2012-01-30

4 risposte

  1. 12

    Il motivo per cui non si ottiene il vostro documenti è che, mentre l’indicizzazione si utilizza StandardAnalyzer, che converte i gettoni e minuscole e rimuove parole. Quindi l’unico termine che viene indicizzata per il tuo esempio è “mezzaluna”. Tuttavia, jolly query non vengono analizzate, in modo da ‘i’ è incluso come parte obbligatoria della query. Lo stesso vale per la frase query nel vostro scenario.

    KeywordAnalyzer probabilmente non è molto adatto per il vostro caso d’uso, perché prende tutto il contenuto del campo come un’unica entità. È possibile utilizzare SimpleAnalyzer per la strada di campo — sarà diviso in ingresso su tutti i caratteri non alfabetici e poi li converte in minuscolo. Si può anche considerare l’utilizzo di WhitespaceAnalyzer con LowerCaseFilter. Hai bisogno di provare diverse opzioni e capire cosa funziona meglio per i vostri dati e utenti.

    Inoltre, è possibile utilizzare diversi analizzatori per campo (ad esempio con PerFieldAnalyzerWrapper) se la modifica analizzatore per il campo interruzioni di altre ricerche.

    OriginaleL’autore Artur Nowak

  2. 6

    Ho trovato che il mio tentativo di generare una query senza l’utilizzo di un QueryParser non funzionava, così ho smesso di provare a creare la mia query e utilizzato un QueryParser invece. Tutti i consigli che ho visto on-line ha mostrato che non si deve usare lo stesso Analizzatore in QueryParser che si utilizza durante il processo di indicizzazione, quindi ho usato un StandardAnalyzer per costruire il QueryParser.

    Questo funziona in questo esempio perché il StandardAnalyzer rimuove la parola “la” strada “la mezzaluna” durante il processo di indicizzazione e quindi non siamo in grado di cercare, perché non è nell’indice.

    Tuttavia, se si sceglie per la ricerca di “Grove Road”, abbiamo un problema con l’out-of-the-box, funzionalità, vale a dire che la query restituirà tutti i risultati che contengono “Bosco” O “Strada”. Questo è facilmente risolto impostando il QueryParser in modo che di default di funzionamento, invece.

    Alla fine, la soluzione corretta è la seguente:

    int numberOfHits = 200;
    String LocationOfDirectory = "C:\\dir\\index";
    TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true);
    Directory directory = new SimpleFSDirectory(new File(LocationOfDirectory));
    IndexSearcher searcher = new IndexSearcher(IndexReader.open(directory);
    
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
    
    //WildcardQuery q = new WildcardQuery(new Term("Street", "the crescent");
    QueryParser qp = new QueryParser(Version.LUCENE_35, "Street", analyzer);
    qp.setDefaultOperator(QueryParser.Operator.AND);
    
    Query q = qp.parse("grove road");
    
    searcher.search(q, collector);
    ScoreDoc[] hits = collector.topDocs().scoreDocs;
    Rimozione di interrompere parole dai nomi delle vie non è corretto. Pensare a nomi come Via. Sono sicuro che è possibile trovare ulteriori esempi vividi. Solo perché togliere qualcosa anche se non ha un senso?

    OriginaleL’autore RikSaunderson

  3. -1

    Se vuoi un’parole esatte partita di strada, è possibile impostare il Campo “Street” NOT_ANALYZED che non filtro interrompere parola “che”.

    doc.add(new Field("Street", "the crescent", Field.Store.YES, Field.Index.Not_Analyzed);
    Questa non è una buona soluzione — in questo modo, si avrebbe bisogno di includere sempre ‘la’ nella query per ottenere questo risultato.
    Nowak: Vota la tua risposta. Adatto Analyzer è il punto.

    OriginaleL’autore 卢声远 Shengyuan Lu

  4. -1

    Non c’è bisogno di utilizzare qualsiasi Analyzer qui coz Sospensione utilizza implicitamente StandardAnalyzer che dividere le parole in base a white spaces quindi la soluzione è impostare il Analyze per NO automaticamente esegue Multi Phrase Search

     @Column(name="skill")
        @Field(index=Index.YES, analyze=Analyze.NO, store=Store.NO)
        @Analyzer(definition="SkillsAnalyzer")
        private String skill;

    OriginaleL’autore Gopi Krishna Seeram

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *