Wie kombiniert man NoSQL mit Volltextsuchen?

Teil 1

22. Februar 2013Kai Spichale

Unternehmen aller Branchen sammeln und speichern mehr und mehr unstrukturierte Daten. Nach allgemein akzeptierten Schätzungen liegen etwa 80% aller unternehmensrelevanten Informationen in unstrukturierter Form vor. Unstrukturierte Daten sind Informationen in einer nicht formalisierten digitalen Struktur. Das heißt jedoch nicht, dass unstrukturierte Daten keine Struktur haben, in der Regel ist diese jedoch nicht geeignet für relationale Datenbanken, die auf Basis eindeutig definierter Schemata arbeiten. Beispiele für unstrukturierte Daten sind E-Mails, Textdokumente, Tabellenkalkulationen und Log-Dateien. Die Informationen in diesen Daten sind für Unternehmen von großer Bedeutung und müssen deswegen leicht zugänglich gemacht werden. Die Struktur dieser Daten, aber auch erhöhte Performance- und Skalierungsanforderungen, hat eine neuen Generation nichtrelationaler Datenbanken hervorgebracht. Einige Vertreter dieser NoSQL-Datenbanken und -Technologien wollen wir unter dem Aspekt der Textsuche näher betrachten. Der erste von zwei Teilen behandelt:

 

Suchserver wie Solr oder elasticsearch

Effiziente Volltextsuchen indizieren die Textdaten vor Durchführung der eigentlichen Suchoperationen. Der dabei gebildete invertierte Index ist eine Datenstruktur, die schnelle wahlfreie Zugriffe auf einzelne Terme in den Dokumenten erlaubt. Die Idee hinter einem invertierten Index ist vergleichbar mit dem eines Stichwortverzeichnisses am Ende eines Buches, mit dem Seiten im Buch zu einem bestimmten Thema schnell gefunden werden können. Ein Index kann wie ein Stichwortverzeichnis die Suchzeit erheblich verkürzen, weil nicht für jeden einzelnen Suchvorgang der gesamte Datenbestand bzw. das gesamte Buch durchsucht werden muss. Allerdings ist der Aufbau eines solchen Index mit einem gewissen Aufwand verbunden. Falls Änderungen an den indizierten Daten vorgenommen werden, muss auch der Index aktualisiert werden. Die wohl bekannteste und leistungsstärkste Open-Source-Suchbibliothek ist Apache Lucene. Sie wird beispielsweise von Wikipedia und Twitter eingesetzt und führt zur Indizierung eine Textanalyse durch. Während dieses Prozesses wird der gegeben Text in eine Menge von Termen durch Tokenisierung, Filtern und Normalisierung konvertiert. Die gebildeten Terme bestimmen, welche Dokumente später mit den Suchanfragen übereinstimmen. Die Konfiguration der Textanalyse hat deswegen einen großen Einfluss auf die späteren Suchergebnisse. Lucene bietet zur Textanalyse eine Mehrzahl sprachspezifischen Analyzer und dazugehörige Filter und Tokenizer an, die in Abhängigkeit der Anwendung, Domäne und Sprache auszuwählen sind. Die sprachspezifischen Analyzer reduzieren die verschiedenen Varianten eines Wortes auf dessen Wortstamm. Durch Stemming oder Lemmantisierung könnten beispielsweise die Wörter „gelesen“ und „las“ auf „les“ zurückgeführt werden. Lucene unterstützt verschiedene Abfragetypen. Neben Term- und Phrasensuche mit Booleschen Operatoren sind auch Wildcard-, Fuzzy- und Bereichssuchen möglich. Da Apache Lucene nur eine Bibliothek ist, empfiehlt sich der Einsatz eines Suchservers wie Apache Solr oder elasticsearch. Diese Standalone-Suchserver bieten eine RESTful API, diverse Konfigurationsmöglichkeiten, Erweiterungen zur Lucene-Suchfunktionalität sowie Techniken für Skalierung und Fehlerbehandlung.

Volltextsuchen werden von uns täglich genutzt, sei es für Recherchen im Internet oder Intranet, bei der Suche nach einer E-Mail im Postfach oder beim Online-Shopping. Entsprechend hoch liegt die Messlatte für Volltextsuchen. Mit der ausgereiften Lucene-Technologie können sehr gute Lösungen umgesetzt werden. Auch NoSQL-basierte Kundenlösungen müssen sich daran messen lassen.

MongoDB

Die dokumentenorientierte Datenbanken MongoDB des adesso Partners 10gen wurde speziell für semi-strukturierte Daten entworfen. MongoDB speichert alle Dokumente intern im BSON-Format, so dass auch tief geschachtelte Strukturen unterstützt werden. Auch das Beispieldokument in diesem Beitrag hier zeigt, dass ein Dokument mehr ist als eine flache Liste bestehend aus Feldern vom Typ String oder Date. Neben einem äußerst flexiblen Datenmodell bietet MongoDB ein umfangreiches Abfragemodell mit zahlreichen Operatoren. Dank der Map-Reduce-Unterstützung können auch komplexe Aggregationen durchgeführt werden.

Bisher war die einzige Möglichkeit, Textsuchen mit MongoDB durchzuführen die Verwendung von Multikey-Indizes. Die Idee besteht darin, den Text eines Feldes in einzelne Wörter zu zerlegen und diese in einem Array redundant zu speichern. Dieses Array wird dann mit einem Multikey Index indiziert, so dass jeder String des Arrays separat erfasst wird. Dieser Ansatz hat jedoch einige Nachteile, die sogar in der offiziellen Dokumentation aufgezählt werden. Die wahrscheinlich größte funktionale Einschränkung dieser Schlüsselwortsuche ist das fehlende Stemming.

Eine andere, deutlich elegantere, Möglichkeit bieten Textindizes, die jedoch in den Release Notes von Version 2.4 noch als experimentell bezeichnet werden. Nichtsdestotrotz ist diese Funktion vielversprechend. Laut den Release Notes werden für die Textanalyse sprachspezifische Stemmer eingesetzt. Die Volltextsuche der in C++ implementierten MongoDB basiert nicht auf Lucene, sondern auf dem Open-Source-Stemmer Snowball. Nach aktuellem Stand werden Phrasen-Suchen sowie Term-Suchen mit optionalen Negationsoperatoren, um Dokumente mit bestimmten Termen zu exkludieren, unterstützt. Das folgende Beispiel sucht Dokumente, in denen das Wort „adesso“, aber nicht das Wort „italienisch“, vorkommt:

db.foo.runCommand(“text“, {search: “adesso –italienisch”, language: “german”})

Auch mehrsprachige Volltextsuchen sind möglich. Falls die eingestellte Standardsprache nicht Deutsch ist, müsste diese, wie im obigen Beispiel, durch das Feld „language“ angegeben werden. Diese Angabe ist wichtig, weil sowohl der Stemmer als auch die Stoppwortliste sprachspezifisch sind. Ein Stoppwort ist ein Wort, das bei der Textanalyse gefiltert wird, weil es sehr häufig vorkommt und deswegen keine Relevanz hat. Typische Stoppwörter sind „und“, „der“, „ein“ und „ist“.

Ein ganz anderer Ansatz wird notwendig, falls Funktionen wie Facettennavigation (faceted search) benötigt werden. Mit Facettennavigation könnten zum Beispiel Autos auf der Website einer Gebrauchtwagenbörse nach spezifischen Kriterien aufgeteilt werden. Kriterien in diesem Zusammenhang könnten u.a. Marken, Modelle und Kraftstoff sein. Man spricht von „Navigation“, weil man durch Auswahl oder Abwahl der Kriterien die Ergebnismenge einschränken oder erweitern kann, bis man gefunden hat, was mach sucht. Facettennavigation wird nicht von MongoDB unterstützt, jedoch von einer separaten Suchmaschine, wie elasticsearch.

Mithilfe des MongoConnectors kann eine MongoDB mit einem anderen System integriert werden. Dieses andere System könnte beispielsweise eine zweite MongoDB sein, die als Failover-System eingesetzt wird, aber in diesem Zusammenhang soll das andere System elasticsearch sein. Nach dem Start kopiert der MongoConnector alle Dokumente zu elasticsearch, wo diese für die Suche indiziert werden. Nachfolgende Dokumentenänderungen in der MongoDB registriert der Connector und überträgt diese zu elasticsearch, so dass beide Systeme kontinuierlich synchron gehalten werden. In diesem Szenario hätte man sowohl die umfangreiche Suchfunktionalität von elasticsearch als auch das umfangreiche Abfragemodell von MongoDB zur Verfügung. Allerdings gibt es einen Wermutstropfen: Die Architektur wird durch den Einsatz beider Technologien komplexer und aufwändiger zu warten und zu betreiben. Es ist daher zu überdenken, ob tatsächlich beide Technologien eingesetzt werden müssen, oder ob die Funktionen einer MongoDB nicht bereits ausreichend sind.

Mit den jüngsten MongoDB-Erweiterungen verschwimmt die Grenze zwischen Datenbank und Suchmaschine, aber auch die Suchmaschinen Solr und elasticsearch erfüllen Persistenz- und Suchfunktionen. Beide können den ursprünglichen Wert eines Feldes unabhängig von dessen Indizierung speichern, so dass sie auch als dokumentenorientierte Datenbanken eingesetzt werden können. elasticsearch unterstützt sogar geschachtelte Felder. Eine interessante Option könnte deswegen der Einsatz von elasticsearch ohne separate MongoDB sein.

Neo4j

Zu einer ganz anderen NoSQL-Spielart gehört Neo4j. Diese Graphdatenbank benutzt die Struktur von Graphen, um Informationen zu speichern. Die Knoten der Graphen repräsentieren persistente Objekte. Die Beziehungen der Objekte zueinander werden durch Kanten ausgedrückt. Die Kanten und Knoten können mit Properties versehen werden. Diese Struktur eignet sich für stark vernetzte Daten und Anwendungsfälle, die durch den Einsatz von Graphenalgorithmen effizient gelöst werden können.

  • Laut Wikipedia und der Kundenliste von Neo Technology setzt der Empfehlungsdienst Moviepilot Neo4j ein. Filmbewertungen von Benutzern werden miteinander auf „geschmackliche Übereinstimmungen“ verglichen, um personalisierte Empfehlungen zu bestimmen.
  • Ein anderes Beispiel ist Viadeo, ein soziales Netzwerk für berufliche Kontakte, das Neo4j als Backend zum Speichern aller Benutzer und ihrer Beziehungen einsetzt. Viadeo ersetzte eine MySQL-basierte Persistenzlösung durch Neo4j und konnte damit Performanceverbesserungen und Speicherplatzreduzierungen erzielen.
  • Auch das Open-Source-Framework für mobile und Web-basierte Anwendungen Structr basiert auf Neo4j. Diese Technologiekombination ist nicht ungewöhnlich, denn Neo4j wurde ursprünglich als Backend für Content Management Systeme (CMS) gebaut. Text, Bilder, Videos, HTML Elemente, Pages und viele andere CMS-Objekte bilden ein Netzwerk, das mit zeitraubenden Join-Operationen relationaler Datenbanken nicht effizient abzurufen wäre.
  • In einer Masterarbeit bei adesso wurde Neo4j zur effizienten Auswertung und Speicherung von Fragebögen, wie sie in der Versicherungsbranche typisch sind, eingesetzt. Die Arbeit zeigte, dass die flexible Struktur eines Graphen besser geeignet ist, dynamische Fragebögen, dazugehörige Antworten und Auswertungsregeln zu erfassen, als vergleichbare relationale Modelle.

Datenabfrage können mit Neo4j mit Gremlin und der Cypher Query Language durchgeführt werden. Wie in der Dokumentation beschrieben ist, könnte man mit folgender Abfrage einen Graphen bestehend aus Benutzern traversieren, beginnend mit Benutzer „Neo“, um alle Follower über die Friend-Beziehung zu identifizieren:

START user=node:node_auto_index(name = ‘Neo’)
MATCH user-[:friend]->follower
RETURN user, follower.name

Neo4j bietet standardmäßig eine Lucene-Integration, die Volltextsuchen nahtlos in die Cypher Query Language integriert. Eine separate Suchmaschine wird dadurch überflüssig. Volltextsuchen können sowohl mit der nativen Neo4j Java API als auch mit Frameworks wie Spring Data Neo4j eingesetzt werden. Zur Integration bietet Neo4j auch eine RESTful API.

Im zweiten Teil dieses Beitrags werden der Wide Column Store Apache Cassandra und die BigData-Plattform Apache Hadoop im Mittelpunkt stehen. Schauen Sie nächste Woche wieder rein!

Kai Spichale Kai Spichale ist Software Architect bei der adesso AG. Sein Tätigkeitsschwerpunkt liegt in der Konzeption und Implementierung von Softwaresystemen auf Basis von Spring und Java EE. Er ist Autor verschiedener Fachartikel und regelmäßiger Sprecher auf Konferenzen.
Artikel bewerten:
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...

Kommentar hinzufügen:

Ihr Kommentar: