7 Stimmen

Lucene-Index mit mehreren Feldern der gleichen Art

Jedes Lucene-Dokument ist ein Rezept, und jedes dieser Rezepte hat Zutaten.

Ich arbeite daran, die Zutaten zu suchen und ein Ergebnis zu liefern, das besagt, dass zwei von vier Zutaten übereinstimmen. (zum Beispiel)

Wie kann ich also die Inhaltsstoffe dem Dokument hinzufügen? In Solr kann ich einfach mehrere Felder erstellen und es würde sie alle speichern, ich könnte etwas falsch machen, weil es nur die eine Zutat speichert.

Dies würde auch für ein Feld wie "Tags" gelten.

p.s Im mit dem Zend Framework für diese, wenn es überhaupt wichtig ist.

14voto

Joel Punkte 28220

Lucene-Dokumente unterstützen das Hinzufügen von mehreren gleichnamigen Feldern, d.h. man kann sie wiederholt aufrufen:

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

Sie sollten also 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 erhalten das Dokument1 zurück. Aber wenn Sie suchen nach:

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

Sie werden nicht zurückkommen Dokument1 .

Wenn Sie gesucht haben:

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

Sie würden auch zurückbekommen Dokument1 .

Wenn Sie sehen möchten, welche Zutaten übereinstimmen, können Sie die Felder des Dokuments einfach als Gespeicherte Felder und rufen dann für jedes übereinstimmende Dokument die Liste der Felder ab und vergleichen sie mit der Benutzerabfrage.

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

Das bedeutet, dass Sie, wenn Sie hinzufügen:

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

dann würde es so behandelt werden, als wäre es eine einzelne Zutat namens "Schoko-Orange", die auf passen könnte:

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

Sie können dies vermeiden, indem Sie einen Wert für PositionIncrementGap > 1 setzen, was zu einem Ergebnis führt:

0 Treffer für:

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

und 1 Treffer für:

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

0voto

Yuval F Punkte 20547

Ich sehe hier zwei mögliche Ansätze:

  1. Denormalisieren Sie Ihre Daten - erstellen Sie für jede Zutat eines Rezepts ein eigenes Dokument und geben Sie allen Dokumenten eines Rezepts eine gemeinsame Rezept-ID. Fassen Sie dann bei der Suche alle Übereinstimmungen mit einer Rezept-ID zusammen. Ein bisschen hässlich.
  2. Verketten Sie alle Ihre Zutaten in einem gemeinsamen Feld, und indizieren Sie es als "Text". Suchen Sie dann mit einer booleschen Abfrage mit "OR" nach Zutaten (in Java Lucene heißt das "Should", das PHP-Äquivalent kenne ich nicht).

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X