Vorwort: wieso ein Blog zu PHP, Solr und Lucene?

Wieso ein Blog zu PHP, Solr und Lucene?
Gegenstand und Ausgangspunkt all unserer Aktivitäten auf diesem Gebiet war ein Projekt um ein Nachrichtenportal und die Aufgabe, Recherchen und Analysen im Nachrichtenbestand von über 10 Million News performant zu handeln. Die MySQL Volltextsuche kam da schnell an Ihre grenzen, Oracle war keine Alternative.
Es reifte also die Frage, wie können andere (etwa die Internetsuchmaschiene google) immense Datenmengen spielend handeln?
Wir lösten den MySQL volltext mit Lucene ab. Der Performancegewinn war dramatisch. Suchen im Datenbestand, die vorher über 10 Sekunden dauerten, brauchen mittels Lucene und Solr nur selten mehr als 20ms!
Eine neue Welt tat sich auf, die es zu erobern galt und schnell fiel auf, dass deutschsprachige Seiten zum Thema Mangelware sind. Dies soll sich mit diesem Blog ein wenig ändern.

Sie haben Fragen zu Solr/Lucene/PHP? Schreiben sie uns einen Kommentar!

Montag, 8. August 2011

Gruppierung von Ergebnissen

Mit Solr 3.4 und Solr 4.0 kommt eine wunderbare, von mir schon lange vermisste Funktion hinzu: das gruppieren von Dokumenten in der Ergebnisliste.
Diese Funktion nennt sich "Field Collapsing" (oder auch "Result Grouping") und ist hier: http://wiki.apache.org/solr/FieldCollapsing beschrieben.

Field Collapsing ist dabei vom Faceted search zu unterschieden:
Beim facettet Search erhalte ich (platt gesagt) die Anzahl (also den nummerischen Wert) eines Suchbegriffes in den verschiedenen Rubriken.  Bspw.: wie oft kommt das Wort "atom" in allen Dokumenten vor, gruppiert nach tagen in bspw täglichen "faceted" Schritten.

Das Gruppieren von Ergebnissen geht dabei einen Schritt weiter, indem nicht nur zurückgegeben wird, wie viele Treffer es für eine Suchphrase je Gruppe gibt, sondern alle gefundenen Nachrichten den jeweiligen Gruppen zuordnet und als Ergebnismenge zurückgegeben werden.
Beispiel: ein Index beinhaltet diverse Nachrichten. Jede Nachricht hat neben der Überschrift, dem Text, etc - auch ein Feld "Sachgebiet", an dem man das Ressort der Nachricht erkennen kann. Mittels Field Collapsing kann ich nun alle Nachrichten nach Ressorts gruppieren.
So können im Ressort "Politik" Meldungen zum Suchwort Atom (über Atomausstiegt, atomare Abrüstung, etc) auftreten als auch im Ressort "Wirtschaft" oder "Vermischtes".

Wir sehen zu jeder Gruppe eine untergeordnete "doclist" mit den entsprecehnden Dokumenten.
Mit solchen Funktionen können beispielsweise Portalseiten wie jene von google News realisiert werden mit Sachgebieten wie "Schlagzeilen", "International", Wirtschaft", etc.

Wie wird nun eine solche Suche realisiert?
Wichtig sind 2 Parameter: group= und group.field=.
Der Parameter group aktiviert lediglich die Funktion FieldCollapsing, group.field= ist das Feld, nach dem Gruppier werden soll. Im obigen Fall das Ressort/Sachgebiet (SACHGEB).
Das oben genannte Ergebnis könnte daher mit folgender URL realisiert werden:
http://localhost:8088/solr/select/?q=atom&group=true&group.field=SACHGEB&fl=SACHGEB,UEBSCHRIFT

Wichtig dabei ist, dass das group.field kein Multivalue-Field ist. Also kein Feld mit mehr als einem Wert.

Ähnlich wie bei der faceted search kann man beim Gruppieren auch numerische Spannen oder Datumsbereiche (Zeiten, Zeitfenster) gruppieren.
Etwa die Gruppierung der Dokumente (hier: Meldungen) nach Monaten: April, Mai, Juni.
Dazu nutzen wir die group.query, welche ähnlich der filer query mehrfach genutzt und kombiniert werden kann. Als zugehörige Datumsspalten greifen wir auf das Feld INDAT zurück, in diesem Feld ist das Eingangsdatum der Dokumente festgeschrieben.
Für jedes gewünschte Zeitintervall definieren wir daher eine group.query. Die URL sähe dann wie folgt aus:
http://localhost:8088
            /solr/select/?q=atom
                         &group=true
                         &group.query=INDAT:[2011-04-01T0:0:0.0Z TO 2011-04-30T23:59:59.9Z]
                         &group.query=INDAT:[2011-05-01T0:0:0.0Z TO 2011-05-31T23:59:59.9Z]
                         &group.query=INDAT:[2011-06-01T0:0:0.0Z TO 2011-06-30T23:59:59.9Z]
                         &fl=SACHGEB,UEBSCHRIFT
...mit dem Ergebnis, dass nun sämtliche, gefundenen Dokumente dank FieldCollapsing in den jeweiligen Monaten gruppiert sind. Sinnvoll an dieser stelle ggf. noch eine filter query auf den Zeitraum Mai-Juni.

Normalerweise liefert Solr pro Gruppe 1 Dokument zurück. aber auch das läßt sich konfigurieren.
Anzahl der gruppierten Elemente läßt sich mittels group.limit= festlegen. Durch group.limit=10 würden im oberen Beispiel 10 Dokumente pro Monat gefunden. Mit dem parameter group.limit=-1 liefert Solr alle vorhandenen Dokumente, zurück, die in eine Gruppe passen. In Test konnte ich allerdings herausfinden, dass hier das Caching faktisch versagt. Selbst wenn das group.limit auf 1000000 steht, ist dies deutlich schneller als der Wert -1. Selbst dann, wenn der gesamte Index nur wenige tausend Dokumente hat.

Keine Kommentare:

Kommentar veröffentlichen