2010-03-09 6 views
6

Jedes Lucene Doc ist ein Rezept, und jedes dieser Rezepte haben Zutaten.Lucene Index mit mehreren Feldern der gleichen Art

Ich arbeite daran, in der Lage zu sein, die Zutaten zu suchen und ein Ergebnis zu geben, das zwei aus vier übereinstimmende Zutaten sagt. (zum Beispiel)

Also, wie kann ich die Zutaten zum Doc hinzufügen? In solr kann ich einfach mehrere Felder von erstellen und es würde alle retten, könnte ich etwas falsch machen, weil es nur die eine Zutat rettet.

Auch dies würde für ein Feld wie "Tags" gelten.

ps Ich benutze das Zend Framework dafür, wenn es überhaupt wichtig ist.

Antwort

12

Lucene-Dokumente unterstützen das Hinzufügen mehrerer Felder mit demselben Namen. das heißt Sie können immer wieder rufen:

document.add(new Field("name"), value) 

So waren Sie zu tun:

# (pseudo-code) 
document1.add(new Field("ingredient"), "vanilla") 
document1.add(new Field("ingredient"), "strawberry") 
index.add(document) 

# And then search for 
index.search("ingredient", "vanilla" && "strawberry") 

Sie document1 zurück. Aber wenn Sie die Suche nach:

index.search("ingredient", "vanilla" && "apple") 

Sie werden nicht wieder document1.

Wenn Sie suchten nach:

index.search("ingredient", "vanilla" || "apple") 

Sie auch zurück document1 bekommen würde.

Wenn Sie sehen möchten, welche Zutaten übereinstimmen, können Sie einfach die Felder im Dokument als Gespeicherte Felder speichern und dann für jedes übereinstimmende Dokument die Liste der Felder abrufen und mit der Benutzerabfrage vergleichen.

Beachten Sie auch, PositionIncrementGap standardmäßig für Felder mit demselben Namen, die zu einem Dokument hinzugefügt werden, ist 0.

Das bedeutet, dass, wenn Sie hinzugefügt:

document1.add(new Field("ingredient"), "chocolate") 
    document1.add(new Field("ingredient"), "orange") 

dann wäre es so behandelt werden, wenn es sich um eine einzelne Zutat „Schokolade orange“ genannt wurden, die auf passen könnte:

index.search("ingredient", "chocolate orange") 

Sie vermeiden können Dies setzt einen Wert für PositionIncrementGap> 1, der folgendes ergibt:

0 Ergebnisse für:

index.search("ingredient", "chocolate orange") 

und 1 Spiel für:

index.search("ingredient", "chocolate" && "orange") 
0

Ich sehe zwei mögliche Ansätze hier:

  1. Ihre Daten denormalisieren - erstellen Sie ein separates Dokument für jeden Bestandteil in einem Rezept, alle Dokumente für ein Rezept-ID ein gemeinsames Rezept geben. Sammeln Sie dann während der Suche alle Übereinstimmungen einer Rezept-ID. Ein bisschen hässlich.
  2. Verketten Sie alle Ihre Zutaten in einem gemeinsamen Feld und indizieren Sie sie als 'Text'. Dann suchen Sie nach Zutaten mit einer booleschen Abfrage mit 'ODER' (Dies wird in Java-Lucene-Termini 'Should' genannt, ich kenne das PHP-Äquivalent nicht).

Ich schlage vor, Sie versuchen den zweiten Ansatz und sehen, ob es hilft.

Verwandte Themen