Entwicklung einer Suchmaschine mit dem Internet Information Server Überblick: Der Index Server erstellt einen Index für alle Inhalte und Eigenschaften von Dokumenten, die auf dem Internet Information Server bereitgehalten werden. Die Clients können Abfragen über ihren Browser mit Hilfe von Formularen erstellen. Diese Abfragen werden an den Index Server weitergeleitet, der sie auswertet und eine Liste der Dokumente an den Server zurückgibt. Diese werden mit ihren URLs dargestellt, so daß direkt von der Anzeige des Suchergebnisses zu den Dokumenten gesprungen werden kann. Voraussetzungen: - Windows NT 4.0 Server (nur für IIS Version 4.0) - Internet Information Server ab Version 2.0 - Microsoft Index Server ab Version 1.0 Abfragen erstellen: Mit dem Index Server gibt es nun die Möglichkeit, die komplette Präsenz zu indizieren und damit einen schnellen Zugriff auf Informationen und eine gezielte Suche in den bereitgestellten Dokumenten zu ermöglichen. Es existieren mehrere Möglichkeiten, eine Suchmaschine mit dem IIS zu erstellen: - Erstellung einer HTML Datei, einer IDQ - Datei und einer HTX Datei - Erstellung eines ASP Scripts - mit Datenbankabfragen (Select,...) Seite 1 von 10
Ich werde exemplarisch die erste Methode beschreiben, welche aus drei Komponenten besteht: Komponenten: - HTML-Dokument: Aus diesem Dokument wird die Abfrage gestartet. Es wird in der Regel ein Formular enthalten. - IDQ Datei: Diese Datei gibt an, in welcher Form die Abfrage verarbeitet werden soll. Sie wird aus dem Formular (HTML Dokument) heraus aufgerufen und stößt die Ausführung des Index Servers an. - HTX Datei: Ein HTML Template um die Ergebnisse der Abfrage zu formatieren und entsprechend anzuzeigen. HTML Dokument: Der Hauptteil dieses Dokuments besteht aus dem Eingabefeld für die Abfrage und einer Schaltfläche für Weiter: <html> <head> <title>einfache Suche</title> </head> <body> <p><font size=+1>simplesearch.html</font></p> <form name="suchform" action="simplesearch.idq"> <b>target:</b> <INPUT TYPE="text" NAME="CiRestriction" SIZE="45" MAXLENGTH="100"> <INPUT TYPE="submit" NAME="goButton" VALUE=" Search "> </form> </body> <INPUT TYPE="HIDDEN" NAME="CiSort" VALUE="rank[d]"> <INPUT TYPE="HIDDEN" NAME="CiMaxRecordsPerPage" VALUE="10"> Der erste Teil dieser Abfrage zeigt das Eingabefeld für die Abfrage und die Schaltfläche an. Eingegeben wird die Abfrage in eine Variable mit der Bezeichnung CiRestriction, allerdings ist der Name hier irrelevant, da in der.idq Datei dieser Name noch umgesetzt werden kann. Hierbei handelt es sich um eine von mehreren speziellen Variablen, die für die Steuerung des Index Server verwendet werden. Im unteren Bereich finden sich mehrere weitere Eingaben für solche Variablen. Diese werden alle für die Steuerung der Abfrage benötigt und bei der Ausführung des Formulars an den Internet Information Server und von diesem wiederum an den Index Server übergeben. Die weiteren Variablen werden später noch eingehend erläutert. Seite 2 von 10
IDQ Datei Von dieser Abfrage ausgehend wird nun das IDQ-Skript SimpleSearch.idq aufgerufen, welches folgendes Aussehen hat (Kommentare wurden entfernt): [Query] CiColumns=doctitle,vpath,filename,size,write,characterization, rank CiFlags=DEEP CiRestriction=%CiRestriction% CiMaxRecordsInResultSet=300 CiMaxRecordsPerPage=%CiMaxRecordsPerPage% CiScope=/ CiTemplate=/inet2/SimpleSearch.htx CiSort=%CiSort% CiForceUseCi=true Neben einer Vielzahl von Zuweisungen passiert hier eigentlich nicht allzu viel. Die in dem HTML-Dokument definierten Variablen werden nur in die entsprechenden Variablen für die Steuerung des Index Server umgesetzt. Sie könnten anstelle der Arbeit mit solchen versteckten Variablen die verschiedenen Variablen auch direkt in der IDQ-Datei definieren. Seite 3 von 10
Von der IDQ Datei benutzte Variablen und deren Bedeutung: Variable CiCatalog CiColumns CiDeferNonIndexedTrimming CiFlags CiForceUseCi CiLocale CiMaxRecordsInResultSet CiMaxRecordsPerPage CiRestriction CiScope CiSort CiTemplate Bedeutung Damit kann gesteuert werden, wo sich der Katalog(index) befindet, der für die Suche verwendet werden soll. Als Standard wird der in der Registry eingetragene Parameter genommen. Gibt die Spalten an, die in der HTX-Datei ausgegeben werden. Die Spalten werden durch Kommanta voneinander getrennt angegeben. Bis zu 50 Spalten mit Informationen können ausgegeben werden. Gibt an, daß die Suchergebnisse optimiert werden sollen, um angegebenen Bereichen, Zugriffsrechten und so weiter zu entsprechen. Diese Optimierung ist sehr zeitintensiv. Schalter für die Tiefe der Suche. Der Wert DEEP gibt an, daß alle Unterverzeichnisse durchsucht werden sollen, während SHALLOW besagt, daß nur das duch CiScope angegebene Verzeichnis durchsucht werden soll. Damit wird gesteuert, daß der Index verwendet wird, auch wenn er nicht mehr aktuell ist. Gibt die Sprache an, in der die Abfrage definiert ist. Maximale Anzahl der Datensätze, die von einer Abfrage zurückgegeben werden sollen. Maximale Anzahl der Datensätze, die auf einer Seite angezeigt werden sollen. Einschränkung für die Abfrage, um zu steuern, nach was gesucht werden soll. Das Startverzeichnis der Suche als virtueller oder physischer Pfadname. Angabe über die Sortierreihenfolge. Durch die Suffixe [a] für aufsteigend und [d] für absteigend kann zusätzlich die Richtung gesteuert werden Die HTX-Vorlage, die für die Ausgabe der Informationen verwendet werden soll. Seite 4 von 10
Nach der Ausführung werden die Ergebnisse in einem HTML-Dokument (auf welches durch die Variable CiTemplate in der IDQ Datei verwiesen wird) angezeigt, das auf der Basis einer Vorlage erzeugt wird. Diese Vorlage trägt in diesem Fall die Bezeichnung SimpleSearch.HTX. Ich werde nun diese Datei abschnittsweise erklären: <html> <head> <title>einfache Suche</title> </head> <body> <p><font size=+1>simplesearch.html</font></p> <form name="suchform" action="simplesearch.idq"> <b>target:</b> <INPUT TYPE="text" NAME="CiRestriction" SIZE="45" MAXLENGTH="100" VALUE="<%CiRestriction%>"> <INPUT TYPE="submit" NAME="goButton" VALUE=" Search "> <INPUT TYPE="HIDDEN" NAME="CiSort" VALUE="rank[d]"> <INPUT TYPE="HIDDEN" NAME="CiMaxRecordsPerPage" VALUE="10"> </form> <hr size=2 noshade> <br> Im oberen Teil der Seite wird erneut die vorherige Seite (die Suchseite) dargestellt, damit nach Einsicht der Suchergebnisse sofort eine weitere Suche gestartet werden kann. <!-- Error Messages --> <%if CiQueryIncomplete ne 0%> <p>the query is too expensive to complete.</p> <%if CiQueryTimedOut ne 0%> <p>the query took too long to complete.</p> Hier wird nun definiert, wie im Fehlerfalle zu verfahren ist, das bedeutet welche Meldungen dem Benutzer auszugeben sind. ne bedeutet ungleich (not equal), eq bedeutet gleich (equal). Seite 5 von 10
<%if CiMatchedRecordCount eq 0%> <p>no matching documents.</p> <%else%> <p><b>found:</b> <%CiMatchedRecordCount%> <b>showing:</b> <%CiFirstRecordNumber%> - <%CiLastRecordNumber%></p> Wenn mehr als 0 Einträge gefunden wurden (CiMatchedRecordCount ungleich 0) werden Informationen angezeigt, wie viel Einträge gefunden wurden und wie viele davon dargestellt werden, ansonsten wird eine Fehlermeldung (No matching documents) ausgegeben. <!-- Detail --> <table border=0> <%begindetail%> <tr> <td valign=top><%cicurrentrecordnumber%>.</td> <td valign=top> <a href="<%escapeurl vpath%>"> <%if doctitle eq "" %> Untitled <%else%> <%doctitle%> </a> <br> <font size=-1><b>url:</b> <%vpath%></font> <br> <font size=-1><%characterization%></font> </td> </tr> <%enddetail%> </table> <br> Dem Block <begindetail> / <enddetail> wird nacheinander jeder Suchtreffer übergeben. Hier wird bestimmt, wie die einzelnen Suchtreffer dargestellt werden. Seite 6 von 10
<!-- Navigation Buttons --> <table border=0> <tr> </tr> </table> </body> </html> <!-- Define a "previous" button if this isn't the first page --> <%if CiContainsFirstRecord eq 0%> <td> <form ACTION="/scripts/SimpleSearch.idq" METHOD="GET"> <input TYPE="SUBMIT" VALUE="Previous <%CiMaxRecordsPerPage%>"> <input TYPE="HIDDEN" NAME="CiBookMark" VALUE="<%CiBookMark%>"> <input TYPE="HIDDEN" NAME="CiBookmarkSkipCount" VALUE="-<%EscapeRAW CiMaxRecordsPerPage%>"> <input TYPE="HIDDEN" NAME="CiMaxRecordsInResultSet" VALUE="<%EscapeRAW CiMaxRecordsInResultSet%>"> <input TYPE="HIDDEN" NAME="CiRestriction" VALUE="<%CiRestriction%>"> <input TYPE="HIDDEN" NAME="CiMaxRecordsPerPage" VALUE="<%EscapeRAW CiMaxRecordsPerPage%>"> <input TYPE="HIDDEN" NAME="CiScope" VALUE="<%CiScope%>"> <input TYPE="HIDDEN" NAME="TemplateName" VALUE="<%TemplateName%>"> <input TYPE="HIDDEN" NAME="CiSort" VALUE="<%CiSort%>"> <input TYPE="HIDDEN" NAME="HTMLQueryForm" VALUE="<%HTMLQueryForm%>"> <input TYPE="HIDDEN" NAME="target" VALUE="<%target%>"> </form> </td> <!-- Define a "next" button if this isn't the last page --> <%if CiContainsLastRecord eq 0%> <td> <form ACTION="/scripts/SimpleSearch.idq" METHOD="GET"> <input TYPE="SUBMIT" VALUE="Next <%CiRecordsNextPage%>"> <input TYPE="HIDDEN" NAME="CiBookMark" VALUE="<%CiBookMark%>"> <input TYPE="HIDDEN" NAME="CiBookmarkSkipCount" VALUE="<%EscapeRAW CiMaxRecordsPerPage%>"> <input TYPE="HIDDEN" NAME="CiMaxRecordsInResultSet" VALUE="<%EscapeRAW CiMaxRecordsInResultSet%>"> <input TYPE="HIDDEN" NAME="CiRestriction" VALUE="<%CiRestriction%>"> <input TYPE="HIDDEN" NAME="CiMaxRecordsPerPage" VALUE="<%EscapeRAW CiMaxRecordsPerPage%>"> <input TYPE="HIDDEN" NAME="CiScope" VALUE="<%CiScope%>"> <input TYPE="HIDDEN" NAME="TemplateName" VALUE="<%TemplateName%>"> <input TYPE="HIDDEN" NAME="CiSort" VALUE="<%CiSort%>"> <input TYPE="HIDDEN" NAME="HTMLQueryForm" VALUE="<%HTMLQueryForm%>"> <input TYPE="HIDDEN" NAME="target" VALUE="<%target%>"> </form> </td> Dieser Code stellt die Next / Previous Buttons dar, entsprechend wo man sich in der Trefferliste gerade befindet. Seite 7 von 10
Von der HTX Datei benutzte Variablen und deren Bedeutung Variable CiBookmark CiContainsFirstRecord CiContainsLastRecord CiCurrentPageNumber CiCurrentRecordNumber CiErrorMessage CiFirstRecordNumber CiLastRecordNumber CiMatchedRecordNumber CiOutOfDate CiQueryIncomplete CiQueryTimedOut CiQueryDate CiQueryTime CiQueryTimeZone CiRecordsNextPage CiTotalNumberPages Bedeutung Referenz auf die erste Zeile der Seite Wird auf 1 gesetzt, wenn diese Seite die erste Zeile der Ergebnisse enthält. Ansonsten ist der Wert 0. Wird auf 1 gesetzt, wenn diese Seite die letzte Zeile der Ergebnisse enthält. Ansonsten ist der Wert 0. Nummer der aktuellen Seite Nummer des aktuell angezeigten Datensatzes. Fehlernachricht. Steht nur bei der Fehlerbehandlung zur Verfügung. Nummer des ersten Datensatzes auf der aktuellen Seite. Nummer des letzten Datensatzes auf der aktuellen Seite. Gesamte Zahl der Datensätze, die von der Abfrage erfasst wurden. Auf 1 gesetzt, wenn der Index nicht mehr aktuell ist. Ansonsten ist der Wert 0. Auf 1 gesetzt, wenn die Abfrage nicht beantwortet werden konnte. Ansonsten auf 0 gesetzt. Auf 1 gesetzt, wenn die Ausführung der Abfrage die definierten Zeitlimits überschritten hat. Ansonsten ist der Wert 0. Datum auf dem Server, an dem die Abfrage ausgeführt wurde. Uhrzeit auf dem Server, an dem die Abfrage ausgeführt wurde. Zeitzone des Servers Anzahl der Datensätze auf der nächsten Seite Gesamtzahl der Seiten, die für die Anzeige der Abfrageergebnisse benötigt werden. Seite 8 von 10
Übungen: Übung 1: Testen Sie die vorgegebenen Beispielseiten auf ihre Funktionalität. Übung 2: Erweitern Sie die Ausgabeseite (.htx) so, daß nun auch die Dateigröße der Suchtreffer angezeigt wird (Variable size). Übung 3: Erweitern Sie die Beispielseite um ein Textfeld, in dem die maximale Anzahl der Datensätze (CiMaxRecordsPerPage), die pro Seite angezeigt werden, eingegeben werden kann. Seite 9 von 10
Anhang: Vergleichsoperatoren in HTX - Dateien EQ wenn Wert1 gleich Wert2 NE wenn Wert1 ungleich Wert2 LT wenn Wert1 kleiner als Wert2 LE wenn Wert1 kleiner oder gleich Wert2 GT wenn Wert1 größer als Wert2 GE wenn Wert1 größer oder gleich Wert2 CONTAINS wenn ein Teil aus Wert1 die Zeichenfolge Wert2 enthält Seite 10 von 10