Suchen und Finden: MyCoRe Query Service

Datenmodell der Suche

Aufgabe des MyCoRe Query Service ist es, gespeicherte Daten durchsuchbar zu machen. MyCoRe Anwendungen suchen dabei nicht direkt in den Metadaten von Dokumenten bzw. deren XML-Darstellung, oder den Volltexten der zugehörigen Dateien, sondern in daraus abgeleiteten Suchfeldern. Die Definition dieser Suchfelder wird für jede MyCoRe Anwendung in der Konfigurationsdatei searchfields.xml vorgenommen (vgl. docportal/config/searchfields.xml). Das XML Schema dieser Datei ist in der Datei searchfields.xsd definiert.

Mehrere Suchfelder werden zu einem Index logisch zusammengefasst. In DocPortal fasst z.B. der Index metadata alle Felder zusammen, die Dokumenten- und Personen-Metadaten durchsuchbar machen. Der Index content enthält alle Felder, die Dateien (deren Volltexte, Dateinamen, Dateigröße etc.) durchsuchbar machen. In jeder MyCoRe Anwendung ist ein Index oder mehrere solcher Indizes in der Datei searchfields.xml definiert. Jeder Index besitzt eine eindeutige ID und besteht aus einem oder mehreren Suchfeldern, die jeweils einen innerhalb der Datei searchfields.xml eindeutigen Namen besitzen.

<searchfields>
  <index id="metadata">
    <field name="title" ... />
    <field name="dateCreated" ... />
    ...
  </index>
  <index id="content">
    <field name="fulltext" ... />
    <field name="size" ... />
    <field name="numPages" ... />
  </index>
</searchfields>

Jedem Index muss ein Searcher zugeordnet werden, der die Felder dieses Index mit Hilfe eines zugrundeliegenden Datenbanksystems (z.B. SQL) oder einer Suchmaschine (z.B. Lucene) durchsuchbar macht. Ein Searcher wird durch eine Java-Klasse implementiert und ist somit zur Laufzeit eine Instanz dieser Klasse.

Searcher
Abbildung 2.5.1: Klasse Searcher

Searcher und Index sind prinzipiell unabhängig, d.h. es ist möglich, je nach Anwendung für den gleichen Index zwischen verschiedenen Searcher-Implementierungen zu wählen, die jeweils Vor- und Nachteile besitzen. Die gleiche Java-Klasse, z.B. die auf Apache Lucene basierende Implementierung eines Searchers, kann auch für mehrere Indizes verwendet werden, so dass zur Laufzeit mehrere Instanzen der Java-Klasse verwendet werden.

Die Zuordnung von Searchern zu Indizes wird in den mycore.properties-Konfigurationsdateien vorgenommen. Jedem Index wird ein Searcher zugeordnet. Jeder Searcher besitzt wiederum eine eindeutige ID. Dazu ein Beispiel:

# Searcher mit ID 'jdom-metadata' sucht im Index 'metadata'
MCR.Searcher.jdom-metadata.Index=metadata
# Searcher mit ID 'lucene-content' sucht im Index 'content'
MCR.Searcher.lucene-content.Index=content
also allgemein
MCR.Searcher.[SearcherID].Index=[IndexID]

Durch die Trennung von Searcher und Index kann man den für einen bestimmten Index verwendeten Searcher durch Änderung nur einer Konfigurationszeile wechseln (z.B. von Lucene auf JDOM). Sie können so in Ihrer Anwendung zu einem späteren Zeitpunkt die Suchimplementierung wechseln, ohne die Daten neu laden zu müssen.

Implementierungen der Suche

Jeder Searcher wird durch eine bestimmte Java-Klasse implementiert.

  • org.mycore.backend.lucene.MCRLuceneSearcher
    verwendet die Apache Lucene Suchmaschine. Dies ist die für Produktionssysteme derzeit empfohlene Implementierung, die sich sowohl für die Metadatensuche, als auch für die Suche in Volltexten eignet.
  • org.mycore.backend.jdom.MCRJDOMSearcher
    verwendet einen Suchindex im Hauptspeicher, so dass keinerlei Daten auf der Festplatte bzw. einem Datenbanksystem gespeichert werden. Diese Implementierung dient als Referenz zur Entwicklung eigener Suchimplementierungen und hat den Vorteil, dass niemals Daten neu indiziert oder geladen werden müssen, eine Änderung der Suchfeld-Konfiguration ist nach Neustart der Anwendung unmittelbar wirksam. Gut geeignet für die Suche in Metadaten bei der Entwicklung einer Anwendung.
Hinweis
Die JDOM-Implementierung der Suche gibt es in Version 2.1 nicht mehr!

Die gleiche Implementierung (Java-Klasse) kann auch für verschiedene Searcher-Instanzen mit unterschiedlicher Konfiguration verwendet werden. Jeder Searcher kann eine eigene, individuelle Konfiguration haben, deren Parameter abhängig von der Implementierung sind. Im folgenden Beispiel wird der Searcher mit der ID lucene-content durch die Klasse MCRLuceneSearcher implementiert. Diese Searcher-Instanz verwendet das Verzeichnis lucene-index4content/, um die Daten des Suchindex zu speichern:

# Konfiguration des Searchers 'lucene-content'
MCR.Searcher.lucene-content.Class=
org.mycore.backend.lucene.MCRLuceneSearcher
MCR.Searcher.lucene-content.IndexDir=/repository/lucene-index4content/

# Konfiguration des Searchers 'jdom-metadata'
MCR.Searcher.jdom-metadata.Class=
org.mycore.backend.jdom.MCRJDOMSearcher
MCR.Searcher.jdom-metadata.Index=metadata
also allgemein
MCR.Searcher.[SearcherID].Class=[ImplementierendeJavaKlasse]
MCR.Searcher.[SearcherID].[KonfigurationsEigenschaft]=[Wert]

Abbildung von Daten auf Suchfelder

Damit die Metadaten bzw. die Dateien der in einer MyCoRe Anwendung gespeicherten Dokumente durchsuchbar sind, müssen diese Daten auf logische Suchfelder abgebildet werden. Diese Abbildung kann je nach Implementierung an sich auf beliebige Weise erfolgen, in der Regel werden aber aus den XML-Darstellungen der Daten die Inhalte der Suchfelder mittels XPath-Anweisungen abgeleitet. Die hierarchische XML-Struktur wird dabei quasi „verflacht“. Mittels Filter (PDF, HTML,OpenOffice etc.) können die Volltexte aus Textdateien extrahiert und einem logischen Suchfeld zugeordnet werden.

Typischerweise werden nicht alle Inhalte auf Suchfelder abgebildet. Ein Suchfeld kann auch eine Aggregation von Daten mehrerer Metadatenfelder sein. Suchfelder sind grundsätzlich auch wiederholbar, da evtl. die zugrunde liegenden Metadatenfelder oder Inhalte wiederholt auftreten. Auch kann das gleiche Metadatenfeld auf mehrere Suchfelder abgebildet werden. Dazu einige Beispiele:

Suchfeld Entsprechung in den Metadaten bzw. Dateien
title /mycoreobject/metadata/titles/title
creator /mycoreobject/metadata/creators/creator
author /mycoreobject/metadata/creators/creator | /mycoreobject/metadata/publishers/publisher
content Volltext der Dateien des Dokumentes
fileSize /file/@size

Suchfelder können nicht nur aus Dokument-Metadaten und Volltexten gebildet werden. Derzeit werden die folgenden Datenquellen unterstützt:

Metadaten der Dokumente (Titel, Autor usw. je nach Datenmodell)

Metadaten der Dateien (Dateiname, Größe, Typ etc.)

Volltext der Dateien:
Dabei wird mittels der in MyCoRe bereitgestellten Filter der Volltext extrahiert und indiziert (z.B. OpenOffice, TXT, HTML, PDF Dateien).

XML-Inhalt der Dateien:
Wenn eine gespeicherte Datei eine XML-Datei ist (z.B. eine Excel-Tabelle, als XML gespeichert, oder eine SCORM-Manifest-Datei eines E-Learning Moduls), können deren XML-Elemente qualifiziert durchsuchbar gemacht werden.

Zusatzdaten der Dateien:
In speziellen Anwendungen können damit z.B. extrahierte ID3-Tags aus MP3-Dateien, EXIF-Daten aus Bildern und ähnliche Quellen durchsucht werden).

Beliebige XML-Quellen:
Eigene Anwendungen können die Inhalte beliebiger XML-Quellen indizieren, ohne dass diese XML-Quellen Teil des MyCoRe Datenmodells sein müssen.

In der Datei searchfields.xml wird für jedes Feld über das Attribut source angegeben, aus welcher Quelle es gebildet wird:

source = MCRFieldDef Konst. Quelle der Feldwerte
objectMetadata OBJECT_METADATA MCRObject.createXML()
objectCategory OBJECT_CATEGORY alle Klassifikationskategorien
fileMetadata FILE_METADATA MCRFile.createXML()
fileAdditionalData FILE_ADDITIONAL_DATA MCRFile.getAdditionalData()
fileXMLContent FILE_XML_CONTENT MCRFile.getContentAsJDOM()
fileTextContent FILE_TEXT_CONTENT MCRFile.getContent() & PlugIn
xml XML beliebiges org.jdom.Document
searcherHitMetadata SEARCHER_HIT_METADATA durch MCRSearcher ergänzt

In allen Fällen außer fileTextContent und searcherHitMetadata (also immer, wenn der Feldwert aus einer XML-Quelle abgeleitet wird) wird über die Attribute xpath und value definiert, wie der Feldwert zustande kommt. Beispiele:

<field name="title" type="text" source="objectMetadata"
  xpath="/mycoreobject/metadata/titles/title" value="text()" />
<field name="fileSize" type="integer" source="fileMetadata"
  xpath="file/@size" value="." />
<field name="content" type="text" source="fileTextContent" />

Das Attribut xpath kann Werte enthalten, wie sie in einem xsl:select- oder xsl:match- Attribut erlaubt sind. Die in searchfields.xml definierten Felder sind grundsätzlich wiederholbar, d. h. wenn etwa ein Objekt mehrere Titel enthält, werden auch mehrere Feldwerte erzeugt und einzeln indiziert.

Ein Sonderfall stellt die Quelle objectCategory dar. Sie muss verwendet werden, wenn nach den Kategorien einer Klassifikation gesucht werden soll. In diesem Fall gibt das xpath-Attribut an, welches Element in den Objektmetadaten den Link auf die Klassifikationskategorien enthält. Das value-Attribut gibt an, ob die ID oder die Labels der Klassifikationskategorie indiziert werden sollen. Beispiel:

<field name="origin" type="identifier" source="objectCategory"
  objects="document" xpath="/mycoreobject/metadata/origins/origin"
  value="@ID" />

Felder mit der Quellangabe searcherHitMetadata werden nicht aus den gespeicherten Daten gebildet, sondern erst bei Zusammenstellen der Trefferliste der Suche von der Suchimplementierung dynamisch ergänzt. Dieser Feldtyp ist für technische Metadaten eines Treffers (score, rank etc.) gedacht. Damit dieses Feld z.B. auch sortierbar ist, muss es in der Datei searchfields.xml definiert sein.

In der Weboberfläche einer MyCoRe-Anwendung kann man sich auf der Metadaten-Detailansicht zu jedem MCRObject über den Parameter ?XSL.Style=searchfields die aus den Metadaten generierten Suchfelder anzeigen lassen. Diese Funktion wird durch den fieldXSL:-URIResolver implementiert und hilft beim Debuggen und Entwickeln der Suchfelddefinitionen einer Anwendung.

http://www.mycore.de:8291/receive/DocPortal_document_07910403?XSL.Style=searchfields

Die Attribute sortable und objects

Suchfelder, nach denen man die Trefferliste der Suche sortieren können möchte, müssen explizit über das Attribut sortable='true' gekennzeichnet werden.

Manche Suchfelder sollen bzw. können nur für bestimmte Objekttypen oder Dateitypen gebildet werden. Über das Attribut objects kann definiert werden, dass ein Suchfeld nur für bestimmte Typen von Metadatenobjekten oder für bestimmte Typen von Dateien (z.B nur denen, für die ein Volltextfilter vorliegt) gebildet werden. Beispiel:

<field name="title" type="text" source="objectMetadata"
  objects="document" sortable="true"
  xpath="/mycoreobject/metadata/titles/title" value="text()" /&gt;

  field name="content" type="text" source="fileTextContent"
  objects="html pdf ps txt xml msword95 msword97 msppt rtf otd sxw" />

Datentypen und Operatoren

Jedem Suchfeld ist ein definierter Datentyp zugeordnet. Der Datentyp bestimmt die möglichen Operatoren für Suchanfragen und legt implizit fest, wie Inhalte dieses Typs behandelt werden (Normalisierung von Umlauten, Stammwortbildung statt exakter Suche etc.). Für jeden Datentyp gibt es eine festgelegte Menge vordefinierter Standard-Operatoren, die jede Searcher-Implementierung unterstützen muss. Darüber hinaus kann eine Implementierung aber auch eigene Datentypen und eigene Operatoren mit erweiterten Suchmöglichkeiten definieren.

Die Definition der Standard-Datentypen und Operatoren erfolgt in der Datei mycore/config/fieldtypes.xml. Das XML Schema dieser Datei befindet sich in mycore/schema/fieldtypes.xsd. Hier ein Auszug als Beispiel:

<fieldtypes>
  <type name="text">
    <operator token="="/>
    <operator token="&gt;"/>
    <operator token="&lt;"/>
    <operator token="&gt;="/>
    <operator token="&lt;="/>
    <operator token="like"/>        <!-- wildcard search using * and ? -->
    <operator token="contains"/>    <!-- words at any position -->
    <operator token="phrase"/>      <!-- a phrase at any position -->
  </type/>
  ...
</fieldtypes>

In zukünftigen Versionen von MyCoRe wird diese Datei auch proprietäre Datentypen (etwa GIS-Koordinaten) und Operatoren (z.B. proximity-Suche in Lucene) definieren und diese als nur durch bestimmte Implementierungen unterstützte Operatoren kennzeichnen. Diese Funktionalität ist derzeit noch nicht implementiert.

Bei der Konfiguration der Suchfelder ist insbesondere auf die richtige Wahl der Textdatentypen zu achten. Es wird zwischen drei verschiedenen Datentypen für Textfelder unterschieden: identifier, name und text. Die folgenden Standard-Datentypen sind derzeit implementiert:

Datentyp Suchoperatoren Beschreibung
identifier =, <, >, <=, >=,like ID, URN, Dateiname etc., also für exakte Werte, keine Normalisierung oderStemming
name =, <, >, <=, >=,like, contains Personen- oder Ortsnamen etc., Umlautnormalisierung, aber kein Stemming
text=, <, >, <=, >=,like, contains,phrase Volltext, Abstract, freier Text, Umlautnormalisierung, Stemming
date =, <, >, <=, >= Datum, vollständig im Format yyyy-MM-dd
time =, <, >, <=, >= Uhrzeit oder zeitliche Dauer, im Format HH:mm:ss
timestamp =, <, >, <=, >= Zeitpunkt, im Format 'yyyy-MM-dd HH:mm:ss'
boolean ='true' oder 'false'
decimal =, <, >, <=, >= Gleitkommazahl,"." als Trennzeichen
integer =, <, >, <=, >= Ganzzahl

Es ist Aufgabe der Suchimplementierung, diese Datentypen auf möglichst geeignete Suchstrukturen (Lucene-/SQL-Typen etc) abzubilden und die Standard-Operatoren in der späteren Suche umzusetzen. Zu beachten ist, dass für Datums-, Zeit- und Boolean-Werte das Format für die Indizierung (wie werden die Felder zur Indizierung übergeben) und die spätere Suche (wie wird ein Wert in einer Query formatiert) exakt festgelegt ist (siehe Formate in obiger Tabelle).

Suchanfragen formulieren

Eine Suchanfrage kann als XML-Dokument oder als Textausdruck formuliert werden. Für Programmierer besteht weiterhin die Möglichkeit, eine Suche als zusammengesetztes Java-Objekt zu formulieren.

Eine einfache Suchbedingung enthält das zu durchsuchende Feld, einen Suchoperator und den Vergleichswert, z.B. Suche nach dem Wort „Optik“ im Titel:

title contains "Optik"

<condition field="title" operator="contains" value="Optik" />

MCRFieldDef titleField = MCRFieldDef.getDef("title");
new MCRQueryCondition( titleField, "contains", "Optik" );

Die Klassen MCRQueryParser und MCRQueryCondition implementieren die Java-Darstellung einer Query bzw. den Parser, um aus der String- oder XML-Darstellung die Java-Darstellung zu gewinnen und zwischen den Darstellungen zu wechseln.

Einfache Suchbedingungen können über and/or/not-Ausdrücke miteinander verknüpft und so zu komplexeren Suchanfragen zusammengesetzt werden:

( not (title contains "Optik") ) and ( date &gt; "2006-02-22" )

<boolean operator="AND">
  <boolean operator="NOT">
    <condition field="title" operator="contains" value="Optik" />
  </boolean>
  <condition field="date" operator="&amp;gt;" value="2006-02-22" />
</boolean>

Solche komplexen Suchbedingungen können über die Klassen MCRAndCondition, MCROrCondition und MCRNotCondition aus dem Paket org.mycore.parsers.bool auch als Java-Objekte gebildet werden.

Normalisierung von Suchanfragen

Suchanfragen werden vor der Ausführung normalisiert. Insbesondere werden Datumsangaben in Suchausdrücken vom eingegebenen Format z.B. 22.04.1971 automatisch in das ISO8601-Format transformiert also 1971-04-22.

Suchbedingungen, die den Operator contains verwenden, werden automatisch in einzelne contains/like/phrase/not-Bedingungen zerlegt. Beispiel:

title contains "-Optik Mecha* 'Lineare Algebra'"

  wird normalisiert zu

(not (title contains Optik)) and (title like Mech*)
and (title phrase 'Lineare Algebra')

In der Konsequenz bedeutet das, dass man bei der Textsuche in aller Regel den Operator contains verwenden kann. Die Umwandlung in eine like- und/oder contains- und/oder phrase-Suche erfolgt automatisch.

  • Worte beginnend mit einem Minuszeichen werden zu einer not-Bedingung.
  • Worte, die * oder ? enthalten, werden zu einer like-Bedingung.
  • Wortgruppen in einfachen Anführungszeichen werden zu einer phrase-Bedingung.

Eine Suchbedingung kann auch gleichzeitig für mehrere Suchfelder definiert werden. Dazu werden die einzelnen Feldnamen durch Kommata getrennt. Beispiel:

title,author contains Goethe

  entspricht

(title contains Goethe) or (author contains Goethe)

Diese Funktionalität kann z.B. verwendet werden, um in einer Suchmaske über nur ein Eingabefeld parallel in mehreren Suchfeldern suchen zu können.
Für ein besseres Verständnis der Normalisierung, hier nochmal eine schematische Darstellung zum Ablauf der Textnormalisierung.

Ablauf Textnormalisierung
Abbildung 2.5.2: Ablauf Textnormalisierung

Suchen mit MCRSearchServlet

Das Servlet MCRSearchServlet führt Suchanfragen aus und stellt die resultierenden Trefferlisten dar. Die Suchanfrage wird auf verschiedene Weisen akzeptiert:

  • Suche in einem vordefinierten Feld:
    In diesem Fall wird nur ein Parameter übergeben, z.B. search=Optik.
    Es wird in einem vordefiniertem Feld mit vordefiniertem Operator gesucht, entsprechend der Konfiguration in mycore.properties:
    MCR.SearchServlet.DefaultSearchField=allMeta
    MCR.SearchServlet.DefaultSearchOperator=contains
    Ein Aufruf mit search=Optik sucht dann nach allMeta contains Optik.
  • Suche mit komplexem Suchausdruck:
    Die Suchanfrage wird dabei im Parameter query übergeben, z.B.
    query=title contains Optik
  • Suche über Namens- und Operator-Parametern:
    Es können mehrere Parameter übergeben werden, deren Namen den definierten Suchfeldern entsprechen müssen. Die einzelnen Bedingungen werden mit UND verknüpft. Beispiel:
    title=Optik&author=Kupferschmidt
    entspricht einer Suche nach
    (title contains Optik) and (author contains Kupferschmidt).
    Wenn, wie im obigen Beispiel, kein Suchoperator angegeben ist, wird der in MCR.SearchServlet.DefaultSearchOperator definierte Wert verwendet. Alternativ kann auch ein Operator angegeben werden:
    title=Opti*&title.operator=like
    entspricht einer Suche nach
    title like Opti*
    Wenn mehrere Werte für ein Suchfeld angegeben werden, werden diese mit dem Operator or verknüpft:
    title=Optik&title=Magnetismus
    entspricht einer Suche nach
    (title contains Optik) or (title contains Magnetismus)

Mit den drei zuvor beschriebenen Methoden kann jede Suche als statischer Link in einer Webseite eingebunden werden. Als weitere HTTP-Request-Parameter können die Anzahl Treffer pro Seite (numPerPage) und die maximale Anzahl auszugebender Treffer (maxResults) angegeben werden. Beispiel:

/servlets/MCRSearchServlet?title=Optik&maxResults=100&numPerPage=5

Die maximale Zahl der gleichzeitig anzuzeigenden Treffer pro Seite kann durch das Konfigurations-Property MCR.SearchServlet.MaxPerPage limitiert werden, und bildet dann eine Obergrenze für numPerPage.

Die Sortierung der Trefferliste kann über einen weiteren Parameter festgelegt werden, durch Anhängen des Suffixes .sortField an den Feldnamen, mit den möglichen Werten ascending und descending:

/servlets/MCRSearchServlet?title=Optik&...&created.sortField=descending

Wenn Sie nach mehr als einem Kriterium sortieren möchten, können Sie die sortField Parameter im Suffix nummerieren, um die Sortierreihenfolge zu bestimmen, z. B.

/servlets/MCRSearchServlet?title=Optik&...&created.sortField.1=descending&author.sortField.2=ascending

  • Suchanfrage als XML-Dokument:
    Hier ist dem MCRSearchServlet ein MyCoRe Editor-Formular vorgeschaltet, das eine Suchmaske darstellt. Nach Abschicken der Suchmaskeneingaben durch den Benutzer generiert das Editor Framework daraus ein XML-Dokument, das die Suchanfrage enthält. Die Syntax dieses XML-Dokumentes entspricht der im vorangehenden Kapitel beschriebenen Syntax für Suchanfragen. Das Wurzelelement query enthält drei Attribute:
    mask
    Dateiname der Suchmaske
    maxResults
    maximale Trefferzahl
    numPerPage
    Anzahl Treffer pro Seite
    Das Element conditions enthält die eigentliche Suchbedingung, entweder formuliert als Menge von verschachtelten XML-Elementen (format=xml) oder als textueller Suchausdruck (format=text). Beispiel:
<query
  mask='editor_form_search-simpledocument.xml'
  maxResults='100' numPerPage='10'>
  <conditions format='xml'>
    <boolean operator='and'>
      <condition field='title' operator='contains' value='Optik' />
      <condition field='author'
            operator='contains' value='Kupferschmidt' />
    </boolean>
  </conditions>
</query>

Nach Ausführung der Suche leitet MCRSearchServlet den Browser direkt zur ersten Trefferseite, es sei denn der Request-Paramter redirect=false wird mitgegeben. In diesem Fall wird direkt die Trefferliste als Response gesendet.

Indizierung von Feldern

Der Query Service ist logisch von der Speicherung der Inhalte unabhängig, so dass Persistenz- und Suchimplementierungen sehr flexibel kombinierbar und austauschbar sind. Dies bedeutet jedoch nicht, dass eine bestimmte Implementierung nicht dennoch beide Dienste gemeinsam realisieren kann. In einer reinen Open Source Umgebung kann z.B. zur Speicherung von Metadaten und Dateien ein lokales Dateisystem dienen, zur Suche in Metadaten und Dateien kann Lucene verwendet werden.

Jedem Index (Menge von Suchfeldern) ist ein Searcher zugeordnet, der diese Felder durchsuchbar macht. Es gibt nun drei Fälle, auf welche Weise diese Felder für eine spezielle Implementierung des Searchers durchsuchbar werden:

  • Es ist keine separate Indizierung notwendig, weil schon durch die Art und Weise der Speicherung der Daten automatisch eine Durchsuchbarkeit gegeben ist (Ausnahmefall), oder:
  • Wenn sich ein MCRObject (Metadaten eines Dokumentes) oder MCRFile (Datei mit Volltext) ändert, wird bei diesem Ereignis über einen speziellen EventHandler, dem Indexer, die Feldwerte aus den Daten extrahiert und in einer eigenen Struktur zwecks Durchsuchbarkeit abgelegt. In der Implementierung gibt es dann zwei Varianten:
    • Der Indexer tut dies selbst, indem er die entsprechenden Event-Methoden überschreibt (Ausnahmefall), oder:
    • Der Indexer wird als Unterklasse von MCRSearcher implementiert und überschreibt die Methoden addToIndex und removeFromIndex (Regelfall). Alle Feldwerte werden dann automatisch durch die Hilfsklasse MCRData2Fields anhand der Konfiguration aus den Daten gebildet.

Aufgabe eines Indexers ist es also, Inhalte auf Suchfelder abzubilden und diese in geeigneten Strukturen in einer Datenbank oder einer Suchmaschine durchsuchbar zu machen. Im Regelfall ist daher nach der Speicherung der Inhalte eine Abbildung von Suchfeldinhalten auf geeignete Backend-Strukturen (SQL-Tabellen, Lucene Index etc). erforderlich. Die Trennung von Such- und Persistenzdiensten und der Aufruf der Indexer erfolgt über den MyCoRe-EventManager. Bei create/update/delete Operationen auf MCRObject (Metadaten) und MCRFile (Dateien) Objekte wird über den Event Manager ein Ereignis ausgelöst, das ein oder mehrere konfigurierte Indexer aufruft. Der Indexer ist dafür verantwortlich, auf die für ihn relevanten Änderungen an Inhalten zu reagieren und ggf. seine Suchfeldeinträge zu aktualisieren.

Jeder Searcher muss als Unterklasse der abstrakten Klasse MCRSearcher implementiert werden. MCRSearcher implementiert bereits das MCREventHandler Interface. Es sind daher drei Fälle realisierbar:

  • Searcher ohne Indexer: Es ist nichts weiter zu tun
  • Searcher mit Indexer, wobei die Indizierung mit eigenen Mitteln erfolgt:
    Die MCRSearcher-Unterklasse überschreibt dann die MCREventHandlerBase Methoden
  • Searcher mit Indexer, wobei die Feldwerte automatisch gebildet werden sollen: Die MCRSearcher-Unterklasse überschreibt die Methoden addToIndex() und removeFromIndex().

Eine Searcher-Implementierung mit Indexer (die also Event Handler ist) kann z.B. wie folgt in den Event-Mechanismus eingebunden werden:

MCR.EventHandler.MCRFile.1.Indexer=lucene-content
MCR.EventHandler.MCRObject.4.Indexer=lucene-metadata

also allgemein:

MCR.EventHandler.[MCRObject|MCRFile].[Nr].Indexer=[SearcherID]

Nun werden bei create/update/>delete Ereignissen auf Metadaten bzw. Dateien die EventHandler-Methoden der implementierenden Klassen aufgerufen. Der typische Ablauf sieht dann in der Implementierung wie in Abbildung 2.5.3 dargestellt aus.

Event-Ablauf
Abbildung 2.5.3: Typischer Event-Ablauf bei der Suche

Suchfeld-Statistiken

In einer Anwendung werden die konfigurierten Suchfelder typischerweise unterschiedlich stark genutzt. Um etwa wenig genutzte Suchfelder gezielt identifizieren zu können, kann man die integrierte Statistik-Funktion verwenden. Diese zählt je Suchfeld die Häufigkeit der Nutzung dieses Feldes in Suchanfragen. Um die Statistik-Funktion zu aktivieren, muss für den jeweiligen Suchindex ein Property gesetzt werden, z. B.

  MCR.Searcher.lucene-metadata.StoreQueryFields=true
     

Beim Beenden der Anwendung werden die Statistiken in eine Property-Datei im "data"-Verzeichnis geschrieben und beim Start wieder eingelesen. Durch die oben beschriebene Konfiguration für DocPortal wird z. B. so die Datei /data/lucene-index4metadata-usage.properties erzeugt.

Suche über Referenzen

In diesem Abschnitt geht es um die Rückgabe von Suchergebnissen über interne Referenzen. Damit ist gemeint, dass in einem Datensatz vom Typ B ein Verweis in Form des Datentyps MCRMetaLinkID auf den Datensatz vom Typ A vorhanden ist. Wird nun im Datensatz B z.B. über eine Klassifikation gesucht, so sollen in der Trefferliste die ID's des referenzierten Datensätze vom Typ A erscheinen.

Um dies zu realisieren, muss die Klasse org.mycore.services.fieldquery.MCRSearcher in den Source-Zweig der betreffenden Applikation kopiert werden. Dort sind die Methoden handleObjectCreated und handleObjectUpdated wie folgend umzugestalten.

...
 String returnID = entryID;
 if (obj.getId().getTypeId().equals("text")) {
   MCRMetaInterface inter =
           obj.getMetadataElement("te43s").getElement(0);
   if (inter != null) {
     returnID = ((MCRMetaLinkID)inter).getXLinkHref();
   }
 addToIndex(entryID, returnID, fields);
 ...