Seit google wissen wir: kein Mensch möchte bei einer Suche/Volltextsuche auf die 2. Ergebnisseite blättern.
So etwa ist die Vorgabe durch den Anwender.
Der Knackpunkt neben validen Suchergebnissen ist also eine möglichst gute Relevanzsortierung.
Glücklicher Weise funktioniert die Relevanzsortierung bei Solr schon sehr gut. Dennoch gibt es je nach Dokumentenart und -inhalt Optimierungspotential.
In unserem Fall werden informelle Volltexte verarbeitet: Nachrichten. Diese haben die Natur, dass in den ersten Zeilen meist Zusammenfassungen, Kontextinformationen oder expemplarische Informationen zur Nachricht selber stehen.
Die ersten Zeilen eines Dokumentes sind also meist besonders inhaltsreich und relevant
Aus diesem Grund bossten wir die ersten N Zeichen eines jeden Dokumentes besonders. Oder anders Gesagt: Teile des eines Textes werden unterschiedlich gewichtet.
Das boosten bzw. höhere Gewichten einzelner Textabschnitte oder Zeilen in Solr funktioniert über einen Trick. Beim Import der Daten aus unserer MySQL Tabelle mittels Data-Import-Handler (DIH) erzeugen wir eine virtuelle Spalte. Diese zusätzliche Spalte befüllen wir mit den ersten N Zeichen des eigentlichen Volltextes. In der data-config.xml des DIH sieht das dann exemplarisch wie folgt aus:
<entity name="tabelle_news" pk="LFNR"
query="SELECT *,
SUBSTRING(TEXT,1,500-CHAR_LENGTH(SUBSTRING_INDEX(SUBSTRING(TEXT,1,500),' ',-1)))
AS TEXT_SNIPPET
FROM tabelle_news
WHERE '${dataimporter.request.clean}' != 'false'
OR LAST_MODIFIED >= '${dataimporter.last_index_time}' - INTERVAL 5 MINUTE">
</entity>
In der Konfiguration des Data-Import-Handler oben wird unmittelbar während des Imports ein maximal 500 Zeichen langer Text Schnipsel aus den ersten Zeichen des Dokumenten-Textes gennerriert und als neues Feld an Solr weiter gereicht. Wichtig ist, nicht blind nach 500 Zeichen abzuschneiden, sondern bereits am Ende des letzten Wortes innerhalb der 500 Zeichen!
Dieses Feld sollte natürlich in der Schema-Datei (schema.xml) entsprechend vorhanden sein, idealer Weise vom gleichen Typ, wie das Volltextfeld.
Wichtig ist, den Textschnipsel auch bei der Suche zu würdigen.
Dazu wird die Datei (solrconfig.xml) entsprechend angepasst.
In unserem Fall kommt der edismax SearchHandler zum Einsatz. Hier kann man explizit angeben, in welchen Feldern er suchen soll und wie Stark die einzelnen Felder gewichtet werden sollen. Exemplarisch könnte der Eintrag wie folgt aussehen:
<requestHandler name="/select" class="solr.SearchHandler" default="true">
<lst name="defaults">
<str name="defType">edismax</str>
<float name="tie">0.01</float>
<bool name="tv">true</bool>
<str name="qf">
AGENTUR^10 UEBSCHRIFT^5.5 TEXT^1.5 THEMA TEXT-EXAKT^7 TEXT_SNIPPET
</str>
<str name="q.alt">*:*</str>
<str name="pf">
AGENTUR^10 UEBSCHRIFT^5.0 TEXT^1.5 TEXT-EXAKT^7 TEXT_SNIPPET
</str>
[...]
Startet ein Anwender eine Suche, so sucht Solr die Informationen in verschiedenen Feldern der Dokumente und gewichtet das Ergebnis abhängig davon, in welchem Feld der gesuchte Begriff auftaucht.
Wichtig ist, dass hier das Feld TEXT_SNIPPET überhaupt erwähnt wird, damit es in der Relevanzberechnung berücksichtigt wird. Je nach Anwendungsfall kann man diesen Bereich natürlich auch noch boosten.
In jedem Fall aber wird nun der erste Teil eines Volltextes/Dokumentes stärker berücksichtigt/gewichtet als der Rest des Dokumentes/Textes.
Deutsche Seite mit Tutorials, HowTo's, und Grundlagen zu Lucene in Verbindung mit Solr und PHP als mächtiges und leistungsfähiges Trio für Voltextsuche und Datenanalysen.
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!
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!
Posts mit dem Label Data Import Handler werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Data Import Handler werden angezeigt. Alle Posts anzeigen
Donnerstag, 18. September 2014
Suchergebnis verbessern: Teile einese Textes unterschiedlich gewichten
Labels:
Data Import Handler,
data-config.xml,
DIH,
Gewichtung Ergebis,
Gewichtung innerhalb eines Text,
Gewichtung Suche,
Relevanz,
solarconfig.xml,
Solr,
Sortierung verbessern,
Suche in mehreren Feldern
Montag, 13. Januar 2014
mongoDB Data Import Handler für Solr
Wie bereits im vorhergehenden Post beschrieben ist derzeit keine Software im Netz verfügbar, die zum einen gepflegt wird und zum anderen performant große Datenmengen einer mongoDB in Solr indexiert.
Die Lösung für uns bestand darin, selber ein kleines Tool zu schreiben, dessen Aufgabe initial darin bestand, eine mongoDB komplett nach Solr zu importieren.
Ich habe es unter github abgelegt, für jedermann zugänglich: mongoSolrImporter
Der klassische Data Import Handler von Solr ist in Solr selber integriert. Der mongoSolrImporter arbeitet im Gegenzug dazu autark als externe PHP Skript.
In einer Konfigdatei werden dazum Solr Server, mongoDB Host, das Field-Mappiung und die mongoDB Query angegeben. Die Konfigurationsdatei wird dann dem Skript übergeben
..und schon kanns losgehen.
Die Daten werden Blockweise in Solr indexiert. Dadurch wird im Vergleich zum mongo-connetor eine deutliche Performancesteigerung. der mongoSolrImporter verarbeitet pro Sekunde 2500 Dateien, wenn man auf einem Linuxsystem arbeitet über 6500 Dateien pro Sekunden, während der mongo-connector bei gleichem Datenbestand auf der gleichen Hardware etwa 33 Dokumente pro Sekunde verarbeitet. Der Geschwindigkeitsgewinn liegt folglich beim Faktor 200.
Zudem basieren die Daten auf einer Query, nicht auf dem oplog der mongoDB. Sind also auch bei abgelaufenem oplog noch greifbar.
Die Beschränkung liegt allerdings in der bisher mangelnden Unterstützung von mongoDB Datentypen. Initial ist das Tool so designt, dass mongoDB Daten verarbeitet werden, die ursprünglich aus einer relationalen Datenbank kommen. Die also keine Arrays oder embedded documents haben.
Die Lösung für uns bestand darin, selber ein kleines Tool zu schreiben, dessen Aufgabe initial darin bestand, eine mongoDB komplett nach Solr zu importieren.
Ich habe es unter github abgelegt, für jedermann zugänglich: mongoSolrImporter
Der klassische Data Import Handler von Solr ist in Solr selber integriert. Der mongoSolrImporter arbeitet im Gegenzug dazu autark als externe PHP Skript.
In einer Konfigdatei werden dazum Solr Server, mongoDB Host, das Field-Mappiung und die mongoDB Query angegeben. Die Konfigurationsdatei wird dann dem Skript übergeben
user@host> php mongoSolrImporter.php -c mongoSolrImporter.ini
..und schon kanns losgehen.
Die Daten werden Blockweise in Solr indexiert. Dadurch wird im Vergleich zum mongo-connetor eine deutliche Performancesteigerung. der mongoSolrImporter verarbeitet pro Sekunde 2500 Dateien, wenn man auf einem Linuxsystem arbeitet über 6500 Dateien pro Sekunden, während der mongo-connector bei gleichem Datenbestand auf der gleichen Hardware etwa 33 Dokumente pro Sekunde verarbeitet. Der Geschwindigkeitsgewinn liegt folglich beim Faktor 200.
Zudem basieren die Daten auf einer Query, nicht auf dem oplog der mongoDB. Sind also auch bei abgelaufenem oplog noch greifbar.
Die Beschränkung liegt allerdings in der bisher mangelnden Unterstützung von mongoDB Datentypen. Initial ist das Tool so designt, dass mongoDB Daten verarbeitet werden, die ursprünglich aus einer relationalen Datenbank kommen. Die also keine Arrays oder embedded documents haben.
Dienstag, 26. November 2013
Solr mongoDB import
Situation
Manchmal ändern sich Situationen und Aufgaben. Im aktuellen Fall geht es darum, mittels Solr die Daten einer mongoDB zu indexieren. Also Solr für die Suche/Volltextsuche in mongoDB zu nutzen. Was wir brauchen ist der Data Import Handler (DIH) für mongoDB, den es so nicht gibt. ut of the Box versteht der DIH nur klassische DB Verbindungen, wie etwa zu MySQL.Erfreulicher Weise ist 10gen, als Entwickler der Mongo DB, daran interessiert, dass sich deren Datenbank etabliert und versorgt die Welt mit diversen Konnectoren, Tools, etc.
Um die Daten der mongoDB in Solr zu indexieren, kann man sich des sogenannten "mongo Connector" bedienen. Ein Python Paket, entwickelt von Praktikanten bei 10gen....
Installation Mongo Connector
Diese Python-Skripte müssen zunächst installiert werden. Laut Doku geht dies mittels 'pip install mongo-connector
' Wer pip nicht nutzt, oder -wie ich- einen Server hat, der nicht mit dem Internet verbunden ist, hat einen weitaus steinigeren Weg.
Zunächst muss neben python auch das Paket 'python-setuptools' installiert, sowie folgende Python-Erweiterungen: urllib3 1.6, requests 2.0.1, pymongo 2.6.3, pyes 0.20.1, pysolr 3.1.0, simplejson 3.3.1. - jewiels bezogen auf den Mongo Connector 1.1.1.
Diese Erweiterungen müssen vorher aus dem Internet heruntergeladen werden. Jedes dieser (G)Zip Archive beinhaltet einen Ordner, in dem sich eine 'setup.py' befindet. In diesem Ordner stehend muss dann das Paket mittels 'python setup.py install' installiert werden.
Anschließend den Mongo Connector (1.1.1) runter laden, auf dem Zielhost entpacken, in das Verzeichnis wechseln und ebenfalls mittels 'python setup.py install' installieren.
Zum Schluss steht ein ausführbares Skript namens 'mongo-connector' bereit.
Funktionsweise Mongo Connector
Diese Connector funktioniert nun so, dass er sich gleichermaßen mit der mongoDB und einem Solr Core verbindet und die Daten aus der mongo Datenbank nach Solr "dumpt".Solr vorbereiten
Dazu habe ich vorher einen neuen Solr Core angelegt, in dem ich ganz trivial die Verzeichnisse eines bestehenden Cores Kopiert und dann das Verzeichnis 'data' geleert habe.
Danach habe ich die 'solr-core/conf/schema.xml' angepasst und Felder analog zum MongoDB Schema angelegt. Auch wenn es ein Oxymoron ist.
Zum Schluss noch in der solr.xml den neuen Core eintragen und solr neu starten.
Solr ist soweit also bereit zur Aufnahme der mongoDB Daten.
Mongo Connector nutzen
Der Mongo Connector arbeitet so, dass er sich mit dem oplog der mongoDB verbindet, diese durcharbeitet und die Daten über einen sogenannten Doc Manager ausgibt. Der Doc Manager ist in unserem Fall ein speziell für Solr geschriebenes Modul des Mongo Connector.
Bei Start des Mongo Connectors werden nun folgende Parameter mit angegeben:
-m Adresse, unter der die mongoDB läuft
-t für den Solr Zielhost
-n für die zu indexierende mongoDB und Collection
-d für den Doc Manager, der die Daten für das Zielsystem (Solr) verarbeitet.
Wichtig: in der hier genutzten mongo Connector Version 1.1.1 gibt es einen Bug. Solr Umgebungen mit mehreren Cores werden nicht unterstützt. Dies stellt sich so dar, dass die Validierung des Zielsystems, in dem Fall der Solr URL, fehlschlägt. Es kommt folgende Meldung:
CRITICAL - MongoConnector: Bad target system URL!
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python2.6/threading.py", line 522, in __bootstrap_inner
self.run()
File "build/bdist.linux-x86_64/egg/mongo_connector/connector.py", line 227, in run
False, self.doc_manager,
AttributeError: 'Connector' object has no attribute 'doc_manager'
Der Workaround sieht so aus, dass man in der Datei '/mongo_connector/doc_managers/solr_doc_manager.py' die Validierung deaktiviert, in dem man folgende Zielen mittels '#' auskommentiert:
# if verify_url(url) is False:
# raise SystemError
Nun kann der import auch mit einem Multi-Core Solr System realisiert werden. Ein beispielhafter Aufruf sieht dabei so aus aus:
# mongo-connector -m localhost:27017 -t http://localhost:8080/solr/mongo -n myMongoDb.myCollection -d ./mongo_connector/doc_managers/solr_doc_manager.py
Erstimport & inkrementeller Import
Der MongoDB Connector legt eine Datei namens 'config.txt' an. Darin wird die oplog-Position vermerkt, bis zu welcher Daten bereits nach Solr eingeflossen sind. Startet man den mongo Connector zu einem späteren Zeitpunkt neu, werden nur die Daten in Solr indexiert, die seit dem letzten lauf das mongo Connectors hinzugekommen sind. Wünscht man einen initialen Neuimport, so muss man die 'config.txt' löschen und dann den connector neu starten.Probleme
Beim mongo Connector gibt es folgende Nachteile zu beachten:- Performance
Jedes Dokument wird einzeln an Solr übergeben und mittels Commit bestätigt. Das ist sehr träge, gerade bei größeren Datenbanken. In einer Testumgebung werden pro Stunden 120.000 Dokumente nach Solr übergeben. Bei einer Datenbank mit bspw. 10 Millionen Dokumenten ist das System über 3 Tage mit dem import beschäftigt. Der klassische Weg über MySQL und Solr DIH (Data Import Handler) benötigt für die gleichen Daten 3 Stunden. - oplog als Basis
Das oplog ist bei mongoDB eine capped Collection. Das heißt, es ist ist davon auszugehen, dass in der DB selber mehr Daten sind, als im oplog. Ein Neuaufbau führt dann dazu, dass nicht alle Dokumente in Solr ankommen. - Buggy
Die Software wurde, vermutlich, mit einem kleinen, konkreten Fokus entwickelt und in die freie Wildbahn entlassen.Anschließend wurden verschiedene Balkone angebaut. In der aktuellen Version gibt es einige Probleme. Bspw. lässt sich das Programm nicht beenden. Nach dem initialen Import werden werden Änderungen in der Mongo-DB nicht Solr repliziert - hier ist ein Neustart erforderlich, etc.
Nachtrag: Wir haben nun einen eigenen Importer entwickelt, über den ich hier berichte: den mongoSolrImporter
Abonnieren
Posts (Atom)