Basic Indexing
Dieser Abschnitt behandelt das Senden von Objekten an Mindbreeze. Sie lernen die Bestandteile eines Crawler kennen und welche Daten für jedes gesendete Objekt bekannt sein müssen.
Objekte an Mindbreeze senden
Um Objekte suchen zu können, müssen zuerst Objekte im Index liegen. Dieses Kapitel erklärt, wie Sie Objekte Ihrer Datenquelle an Mindbreeze schicken können. Es ist sehr einfach ein Objekt suchbar zu machen, die folgenden Zeilen genügen, um ein Objekt mit dem Titel „title“ und dem key „1“ im Index abzulegen:
Indexable indexable = new Indexable(); indexable.setKey("1"); indexable.setTitle("title"); client.filterAndIndex(indexable);
Rund um diese Zeilen gibt es noch einige Dinge zu klären. Zuallererst müssen Sie sich Gedanken darüber machen, welche Dokumente aus Ihrer Datenquelle relevant für die Suche sind.
Welche Objekte gibt es in meiner Datenquelle?
Wenn man einen neue Datenquelle zur Suche hinzufügen möchte, sollte man sich immer Gedanke darüber machen, welche Inhalte für die Benutzer interessant sind.
Dieses Beispiel verwendet beliebige CMIS-Services als Datenquelle. CMIS bietet vier unterschiedliche Objekttypen: Folders, Documents, Relationsships und Policies. Hier werden ausschließlich Dokumente gesendet.
Wie werden Objekte gesendet? Welcher Prozess kümmert sich darum?
Mindbreeze verwendet Crawler, um Objekte an den Index zu senden. Ein Crawler kennt die Datenquelle und sendet die darin enthaltenen Objekte zur Indizierung. Für jeden Datenquellentyp gibt es einen Crawler. Für Mindbreeze InSpire gibt es unter anderem einen Microsoft Exchange Crawler und einen Microsoft SharePoint Crawler. Wir bieten die gleiche Pluginschnittstelle, die wir für unsere Crawler verwenden, auch in unserem SDK an.
Als ersten Schritt sollten Sie den Beispielcrawler als Plugin paketieren und in Ihrer Appliance einspielen. Klicken Sie mit der rechten Maustaste auf die Datei build.xml und wählen Sie Run As > Ant Build
aus.
![Run as \](https://www.mindbreeze.com/sites/all/themes/mindbreeze/images/inapp.mindbreeze.com/m/2a/run_as.png)
Dadurch wird im Verzeichnis build
die das Plugin-Archiv cmis-datasource.zip
angelegt.
Nun muss das Plugin noch in der Appliance hinterlegt werden. Öffnen Sie dazu die Konfigurationsoberfläche von Mindbreeze und wechseln zum Karteireiter Plugins. Wählen Sie die Zip-Datei aus und bestätigen Sie mit Upload.
![Plugins](https://www.mindbreeze.com/sites/all/themes/mindbreeze/images/inapp.mindbreeze.com/m/d2/2_plugins.png)
Nun ist das Plugin installiert.
Legen Sie nun einen Index an und fügen Sie eine neue Datenquelle hinzu.
![Add new datasource](https://www.mindbreeze.com/sites/all/themes/mindbreeze/images/inapp.mindbreeze.com/m/5/3_neue_datenquelle.png)
Ein Objekt senden
Die wichtigste Klasse für den CMISCrawler ist mindbreeze.example.cmis.crawler.CmisCrawler
. Diese implementiert die Pluginschnittstelle für Crawler.
com.mindbreeze.enterprisesearch.mesapi.crawler.Crawler: public interface Crawler { public void init (Configuration configuration); public void performCrawlRun(FilterAndIndexClient client) throws Exception; public void shutdown(); }
Die init
-Methode dient zur Vorbereitung des Crawlers auf die Crawlläufe. Hier können z.B. Datenbankverbindungen aufgebaut werden. Das Gegenstück dazu ist die shutdown
-Methode. Sie wird vor dem Beenden des Crawlers aufgerufen.
performCrawlRun
wird für jeden Crawllauf aufgerufen. Hier werden die Objekte von der Datenquelle indiziert. Der Aufruf
client.filterAndIndex(indexable);
sendet ein Objekt.
Das Indexable
-Objekt dient zur Sammlung der relevanten Daten für ein übermitteltes Objekt. Das folgende minimale Beispiel bereitet ein Objekt für die Indizierung vor:
Indexable indexable = new Indexable(); indexable.setKey("1"); indexable.setTitle("my title");
Für das Objekt wir der key
gesetzt, der Schlüssel für ein Objekt in einer Datenquelle. Der title
setzt den Titel des Objekts.
Sie können jetzt bereits im Mindbreeze Web Client nach dem indizierten Dokument suchen.
Wichtig: Bei der Definition des keys ist zu beachten, dass jeder Crawler für mehrere Datenquellen des Typs konfiguriert werden kann. Dieses Beispiel kann Objekte von CMIS Datenquellen indizieren. Es können mehrere Crawler konfiguriert werden, z.B. für Fabasoft Folio Cloud Österreich und Fabasoft Folio Cloud Deutschland.Damit ein Objekt über Datenquellen hinweg eindeutig identifiziert werden kann, besteht der Schlüssel im Index aus 3 Teilen. Der Art der Datenquelle (Category), der Datenquelle (Category Instance) und dem key. Die Category wird für das Plugin festgelegt. Die Category Instance kann in der Konfigurationsoberfläche eingestellt werden:
![Data Sources - Category Instance](https://www.mindbreeze.com/sites/all/themes/mindbreeze/images/inapp.mindbreeze.com/m/ca/4_advanced_settings.png)
Für das Beispiel können sie die Standardeinstellung verwenden. Sie müssen aber beachten, dass beim Anlegen einer weiteren Datenquelle eine andere Category Instance eingestellt wird, da sonst Objekte von z.B. Fabasoft Folio Cloud Österreich die Objekte von Fabasoft Folio Cloud Deutschland überschreiben.
Angezeigtes Datum und Änderungsdatum
Um das angezeigte Datum beim indizierten Objekt zu setzen, verwenden Sie setDate
.
indexable.setDate(cmisDocument.getCreationDate());
Nach diesem Datum wird auch sortiert, falls Sie nach Datum sortieren.
Zusätzlich zum angezeigten Datum gibt es das Änderungsdatum des Dokuments. Dieses Datum wird verwendet um festzustellen, ob sich ein Dokument geändert hat oder nicht.
indexable.setModificationDate(cmisDocument.getLastModificationDate());
Alle Datumswerte müssen in UTC umgerechnet gesendet werden. Nur dadurch ist sichergestellt, dass die Werte korrekt dargestellt werden und es zu keinen Problemen mit unterschiedlichen Zeitzonen oder Sommer- und Winterzeit kommt.
Inhalte und Dateien senden
Im vorigen Abschnitt wurde ein einzelnes Objekt mit Titel und key indiziert. Mindbreeze bietet eine sehr einfache Möglichkeit den Inhalt eines Objekts zu indizieren. Sie haben die Möglichkeit bestehende Dateien direkt zu senden und das Mindbreeze Filter Service sämtliche Inhalte aus den Dokument herausfinden zu lassen. Wichtig sind dafür die Methoden setContent
und setExtension
. An setContent
übergeben Sie die Bytes des Inhalts. Mit setExtension
legen Sie den Dateityp des Inhalts fest. Wenn Sie hier z.B. doc angeben und content die Daten eines Word-Dokuments enthält, findet der Filter automatisch den Inhalt und zusätzliche Information, wie den Autor, heraus.
Sie können aber auch einfach eine Zeichenkette als Inhalt senden.
indexable.setContent("content".getBytes("utf-8")); indexable.setExtension("txt");
Zusammenfassend, der Inhalt eines Objekts wird mit den Eigenschaften content
und extension
festgelegt. In content werden die Daten des Inhalts übertragen. Extension txt bedeutet, dass der Inhalt als Textdokument betrachtet wird.
Alle CMIS-Dokumente indizieren
Das Beispielprojekt durchläuft alle verfügbaren Ordner und ruft für jedes Dokument die Methode buildIndexable
auf. Hier wird ein Indexable-Objekt mit den gewünschten Werten erzeugt.
private Indexable buildIndexable(Document cmisDocument) throws IOException { Indexable indexable = new Indexable(); indexable.setKey(cmisDocument.getId()); indexable.setTitle(cmisDocument.getName()); indexable.setDate(cmisDocument.getCreationDate()); indexable.setModificationDate(cmisDocument.getLastModificationDate()); byte[] content = getContentBytes(cmisDocument.getContentStream()); indexable.setContent(content); String extension = getExtension(cmisDocument); indexable.setExtension(extension); return indexable; }
Die Suche im Mindbreeze Web Client liefert jetzt alle Dokumente des Demo-Benutzers in Fabasoft Folio Cloud.
Eigenschaften indizieren und suchen
Das Beispiel indiziert aktuell Titel Inhalt und Datum. Mindbreeze bietet aber die Möglichkeit beliebige Eigenschaften pro Objekt zu hinterlegen. Eigenschaften werden mit indexable.putProperty
angegeben.
indexable.putProperty(NamedValue.newBuilder() .setName("name") .addValue(ValueHelper.newBuilder("value")) );
Um einen Listenwert abzubilden, genügt ein mehrfacher Aufruf von addValue
:
indexable.putProperty(NamedValue.newBuilder() .setName("name") .addValue(ValueHelper.newBuilder("value")) .addValue(ValueHelper.newBuilder("value")) );
Die hinzugefügten Eigenschaften sind bereits im Index enthalten und auch durchsuchbar. Sie können z.B. eine Suche nach name:value machen und erhalten nur die Objekte, die name auf value gesetzt haben.
Anzeige der Eigenschaften im Mindbreeze Client
Damit die Eigenschaften auch im Mindbreeze Client angezeigt werden, müssen sie im CategoryDescriptor eingetragen werden. Jede Eigenschaft, die angezeigt werden soll, muss als metadatum
eingetragen werden. Sie können durch name
-Elemente die Übersetzung für die Bezeichnung angeben.
<metadatum id="name"> <name xml:lang="de">Name de</name> <name xml:lang="en">Name en</name> </metadatum>
Nach der Änderung des CategoryDescriptors muss das Plugin neu paketiert und eingespielt werden.
Anzeige der Eigenschaften mit SearchService
Das SearchService liefert die Werte, die auch im Client Service angezeigt werden. Sie können also auch den CategoryDescriptor anpassen, wie im Kapitel "Eigenschaften indizieren und suchen" unter "Anzeige der Eigenschaften im Mindbreeze Client" beschrieben. Sie können aber auch mit addRequestProperty
Eigenschaften bei der Suche anfordern.
QueryExpr query = QueryExpr.newBuilder().setKind(QueryExpr.Kind.EXPR_UNPARSED).setUnparsedExpr(userQuery).build(); SearchRequest searchRequest = SearchRequest.newBuilder() .setRankingStrategy(RankingStrategy.RANK) .setDetailLimit(DetailLimit.CONTENT) .setUserQuery(query) .addRequestedProperty(PropertyDefinition.newBuilder().setName("title")) .addView(View.newBuilder() .setId(View) .setCount(10) .setRankingStrategy(mindbreeze.query.ViewProtos.View.RankingStrategy.RELEVANCE) ) .build();
Sie erhalten ein exakt gleiches Value-Objekt, das Sie bei der Indizierung angegeben haben.
Statt einer einfachen Unparsed-QueryExpr können Sie auch eine Labeled-QueryExpr verwenden. Damit können Sie den Namen der Eigenschaft getrennt vom Suchbegriff definieren.
QueryExpr query = QueryExpr.newBuilder() .setKind(QueryExpr.Kind.EXPR_LABELED) .setNamedExpr(Labeled.newBuilder() .setLabel("name") .setExpr(QueryExpr.newBuilder() .setKind(QueryExpr.Kind.EXPR_UNPARSED) .setUnparsedExpr("value") ) ).build();
Dies ist zum Beispiel nützlich, wenn es ein Eingabefeld für eine Eigenschaft gibt. Dann ist der Eigenschaftsname fix definiert, und die Benutzereingabe wird als Suchbegriff verwendet.
Datentypen
Die bisherigen Beispiele zeigen, wie String-Werte hinzugefügt werden. Mindbreeze InApp findet in solchen Eigenschaften automatisch Zahlen. Sie können zum Beispiel die Eigenschaft Version auf 12 setzen und Mindbreeze interpretiert die Zahl darin. Sie können dann z.B. nach Version:12 TO 24 suchen. Diese Funktion erlaubt auch die Verwendung von Version mit dem Wert „Version 12“. Die Einschränkung kann unverändert bleiben.
Zahlen können aber auch als Zahlenwerte angegeben werden. Dadurch kann die Bereichssuche beschleunigt werden und Sie erhalten einen Zahlenwert, wenn Sie das SearchService
nutzen. Mit folgendem Beispiel können Sie ganze Zahlen indizieren:
indexable.putProperty(NamedValue.newBuilder() .setName("version") .addValue( Value.newBuilder() .setKind(Value.Kind.INTEGER) .setIntegerValue(12) ) );
Damit der Qunatity-Werte durchsucht werden können, muss im CategoryDescriptor für die Metadaten das Attribut regexmatchable
auf true
gesetzt werden.
Version
Die Suche ist mit version:[12] oder version:[10 TO 20] möglich.
Zusätzlich zu einfachen Zahlenwerten sind auch Datumswerte möglich:
indexable.putProperty(NamedValue.newBuilder() .setName("mydate").addValue( ValueHelper.newBuilder(Indexable.getCalendarFromDate(new Date()))) );
Die Suche mydate:[2003-01-01 TO 2023-01-01] schränkt die Resultate anhand mydate zwischen 2003 und 2023 ein.
Genau so schränkt documentsize auf Dateigrößen ein:
indexable.putProperty(NamedValue.newBuilder() .setName("documentsize").addValue( ValueHelper.newBuilder( QuantityHelper.newBuilder( Quantity.Kind.INFORMATION_STORAGE, content.length))) );
Facetten
Facetten erlauben dem Benutzer die Suchresultate aufgrund der Inhalte des Index einfach zu verfeinern.
![Facetten](https://www.mindbreeze.com/sites/all/themes/mindbreeze/images/inapp.mindbreeze.com/m/b/5_facetten.png)
Damit indizierte Eigenschaften als Facetten verwendet werden können, muss im CategoryDescriptor für die Eigenschaft das Attribut aggregatable
auf true gesetzt werden.
Wichtig: Facetten stehen aktuell nur String-Werte zur Verfügung.
Facetten werden im Mindbreeze Client automatisch angezeigt, können aber mit der Option Aggregations deaktiviert werden.
![Aggregations](https://www.mindbreeze.com/sites/all/themes/mindbreeze/images/inapp.mindbreeze.com/m/95/6_client20servies.png)
Im Search Service stehen die gleichen Facetten zur Verfügung wie im Client Service. Sie können aber auch beliebige Facetten mit addAggregation
bei einer View anfordern.
… View.newBuilder() .setId("View") .setCount(10) .addAggregation("name") …
Die Facetten sind als List von Aggregation-Objekten im ResultSet enthalten.
<% for (Aggregation aggregation : resultSet.getAggregationList()) { if (aggregation.getEntryCount() == 0) continue; %> <div class="facet"> <div class="facetName"> <b><%="mes:date".equals(aggregation.getName())? "Datum" : aggregation.getName()%></b> </div> <div class="facetEntries"> <% for (Aggregation.Entry entry : aggregation.getEntryList()) { byte[] queryExpr = entry.getQueryExpr().toByteArray(); String facetQuery = Base64.encodeBase64URLSafeString(queryExpr); %> <div><a href="<%=Nav.self(request, "start", "0")%>&facet=<%=facetQuery%>"><%= entry.getName() %> (<%= entry.getCount() %>)</a></div> <% } %> </div> </div> <% } %>
Jede Ausprägung der Facetten enthält den Wert der Eigenschaft, die Anzahl der Objekte, sowie ein QueryExpr-Objekt, für die Einschränkung der Dokumente. Dieses QueryExpr-Objekt können Sie bei der Suche zur Einschränkung verwenden.
QueryExpr.And.Builder constraints = QueryExpr.And.newBuilder(); String[] facets = request.getParameterValues("facet"); if (facets != null) { for (String facet : facets) { if (facet.isEmpty()) continue; QueryExpr queryExpr = QueryExpr.newBuilder().mergeFrom(Base64.decodeBase64(facet)).build(); constraints.addExpr(queryExpr); } } if (constraints.getExprCount() > 0) { searchRequest.setQueryConstraints(QueryExpr.newBuilder() .setKind(QueryExpr.Kind.EXPR_AND) .setAndExpr(constraints) ); }
Download
Zugang zum Mindbreeze InSpire SDK Download-Bereich.