2010-04-13 4 views
10

In der Abfragesyntax Lucene Ich mag * kombinieren und ~ in einer gültigen Abfrage wie: bla ~ * // ungültige AbfrageLucene Abfrage: bla ~ * (Wörter, die mit etwas Fuzzy beginnen), wie?

Bedeutung: Bitte Worte übereinstimmen, die ähnlich mit „bla“ oder etwas anfangen, "bla".

aktualisieren: Was ich jetzt tun, arbeitet für kleinen Eingang, ist die folgende (Snippet SOLR Schema) verwenden:

<fieldtype name="text_ngrams" class="solr.TextField"> 
    <analyzer type="index"> 
     <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
     <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
     <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/> 
    </analyzer> 
    <analyzer type="query"> 
     <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
     <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
    </analyzer> 

Falls Sie verwenden SOLR nicht, das macht folgendes.

Indextime: Indexdaten durch Erstellen eines Feldes, das alle Präfixe meiner (kurzen) Eingabe enthält.

Suchzeit: Verwenden Sie nur den Operator ~, da die Präfixe explizit im Index vorhanden sind.

Antwort

2

Ich glaube nicht, dass Lucene so etwas unterstützt, noch glaube ich, dass es eine triviale Lösung hat.

"Fuzzy" -Suchen funktionieren nicht mit einer festen Anzahl von Zeichen. bla~ kann beispielsweise blah entsprechen und so muss der gesamte Begriff berücksichtigt werden.

Was Sie tun können, ist eine Abfrage Expansionsalgorithmus implementieren, der die Abfrage nahm bla~* und wandelte sie in eine Reihe von OR-Abfragen

bla* OR blb* OR blc OR .... etc. 

Aber das ist wirklich nur durchführbar, wenn die Zeichenfolge sehr kurz ist oder wenn Sie kann die Erweiterung basierend auf einigen Regeln eingrenzen.

Alternativ, wenn die Länge des Präfixes fest ist, können Sie ein Feld mit den Teilstrings hinzufügen und die unscharfe Suche darauf durchführen. Das würde Ihnen das geben, was Sie wollen, wird aber nur funktionieren, wenn Ihr Anwendungsfall ausreichend eng ist.

Sie geben nicht genau an, warum Sie dies benötigen, vielleicht werden dadurch andere Lösungen ausgelöst.

Ein Szenario, das mir einfällt, ist der Umgang mit verschiedenen Formen von Wörtern. Z.B. Suche nach car und cars.

Dies ist einfach in Englisch, da Wortstammer verfügbar sind. In anderen Sprachen kann es ziemlich schwierig sein, Wortstammerzeuger zu implementieren, wenn nicht unmöglich.

In diesem Szenario können Sie jedoch (vorausgesetzt Sie haben Zugriff auf ein gutes Wörterbuch) den Suchbegriff nachschlagen und die Suche programmgesteuert erweitern, um nach allen Formen des Wortes zu suchen.

z. Eine Suche nach cars wird in car OR cars übersetzt. Dies wurde erfolgreich für meine Sprache in mindestens einer Suchmaschine angewendet, ist aber offensichtlich nicht trivial zu implementieren.

+0

Althoug Fuzzy-Suche funktioniert nicht auf einer bestimmte Anzahl von Zeichen, für meinen Fall einfach mit ~ nicht funktionieren (zu großem diff in char count). Ich möchte z.B. Sunla nach Sundlaugarvegur. –

+0

natürlich, wenn ich Lucene nur auf die ersten x Zeichen jedes Wortes im Index übereinstimmen könnte, würde ~ funktionieren ... –

+0

Sie müssten hier über Lucene gehen, verwenden Sie einen String-Vergleich Algorithmus wie Levenstein, Jaro -Winkler usw. (s. Unten) – Mikos

0

Sie meinen, Sie möchten eine Wildcard und Fuzzy-Abfrage kombinieren?Sie könnten eine Boolesche Abfrage mit einer OR-Bedingung verwenden zu kombinieren, zum Beispiel:

BooleanQuery bq = new BooleanQuery(); 

Query q1 = //here goes your wildcard query 
bq.Add(q1, BooleanClause...) 

Query q2 = //here goes your fuzzy query 
bq.Add(q2, BooleanClause...) 
+0

Ich glaube nicht, dass dies erreichen würde, was das OP verlangt, da es im Grunde "bar ~ OR bar *" werden würde, was nicht dasselbe ist wie "bar ~ *" und nicht finden würde (zum Beispiel) "Brafoo". – Kris

+0

yup, das ist nicht, was ich will :) –

+0

Ok, danke für die Klärung, einen Ansatz, den ich verwendet habe (für die passenden Namen von Proteinen etc.) mit String-Abständen wie Smith-Waterman, Jaro-Winkler etc. Ein Werkzeug wie SimMetrics könnte Hilfe geben http://www.dcs.shef.ac.uk/~sam/simmetrics.html – Mikos

1

Es für einen Adresssuchdienst ist, wo ich will Adressen vorschlagen, basierend auf teilweise eingegeben und möglicherweise falsch geschriebene Straßennamen/citynames/etc (any Kombination). (Man denke an Ajax, Benutzer die Eingabe einer teilweisen Straßenadressen in einem Textfeld)

Für diesen Fall die vorgeschlagene Erweiterung der Suchanfrage ist vielleicht nicht so durchführbar, da die Teilfolge (Adresse) kann länger werden als „short“ :)

Normalisierungs

Eine Möglichkeit, die ich denken kann ist string „Normalisierung“, anstelle von Fuzzy-Suche zu verwenden, und einfach mit Wildcard-Abfragen zu kombinieren, dass. Eine Straßenadresse von

"miklabraut 42, 101 reykjavík", würde "miklabrat 42 101 rekavik" werden, wenn normalisiert.

So Gebäude Index wie diese:

1) baut den Index mit Aufzeichnungen „normalisiert“ -Versionen von Straßennamen, Ortsnamen usw., mit einer Adresse pro Dokument (1 oder mehr Felder) enthalten.

die Suche und der Index wie diese:

2) Normalisieren inputstrings (z.B. mikl reyk) verwendet, um die Anfragen zu bilden (d.h. mik rek). 3) Verwende den Platzhalter op, um die Suche durchzuführen (d. H. mik* AND rek*), wobei der unscharfe Teil weggelassen wird.

, die fliegen würde, vorausgesetzt, der Normalisierungsalgorithmus ist gut genug :)

7

in der Entwicklung Stamm lucene (noch nicht ein Release), gibt Code Anwendungsfälle wie diese zu unterstützen, über AutomatonQuery. Warnung: Die APIs können/werden sich vor der Veröffentlichung ändern, aber es gibt Ihnen die Idee. Hier

ist ein Beispiel für den Fall:

// a term representative of the query, containing the field. 
// the term text is not so important and only used for toString() and such 
Term term = new Term("yourfield", "bla~*"); 

// builds a DFA that accepts all strings within an edit distance of 2 from "bla" 
Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2); 

// concatenate this DFA with another DFA equivalent to the "*" operator 
Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString()); 

// build a query, search with it to get results. 
AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix); 
+0

Ich bin gerade auf diese Frage zurückgekommen und habe deine Antwort wieder gesehen. Hast du es versucht? Was ich jetzt mache (funktioniert für kleine Eingabe), ist, alle Präfixe meiner Eingabe zu erzeugen und die Präfixe in den Index zu setzen.Dann brauche ich nur den Operator ~ und bekomme Funktionalität wie ~ * –

+0

Ihre Workaround ist gut für kleine Eingaben ... aber wie Sie angedeutet haben, wird ein Problem für große Eingaben sein: Sie werden eine große Menge an Begriffen hinzufügen und Postings für alle diese Präfixe ... das wird die Fuzzy-Abfrage vor Lucene 4.0 noch langsamer machen, da es einen linearen Scan aller Terme macht. –

+0

Gibt es eine Lucene-Abfragesyntax, die Ihnen den Zugriff auf die Automaten-Abfrage durch Solr ohne Programmierung ermöglicht? – wrschneider

Verwandte Themen