Redazione
a- a+

Motore di ricerca in ASP

Vediamo come realizzare in modo semplice e veloce un motore di ricerca interno per un sito. Codice ed esempio

Introduzione
Un motore di ricerca interno è uno strumento molto importante per i siti web, soprattutto di media-grandi dimensioni. Pensate a WebMasterPoint.org che ha oltre 4.000 pagine di articoli, tutorial... come farebbe senza un motore di ricerca? Esistono essenzialmente tre modi di realizzare un motore di ricerca interno:

  • utilizzando un motore esterno (esistono servizi gratuiti e a pagamento esterni, ma anche con lo stesso Google è possibile fare ricerche interne al proprio sito web)
  • utilizzando un archivio su database
  • utilizzando l' Index Server

Noi analizzeremo le ultime due possibilità, visto che sono facilmente realizzabili in ASP.

Il progetto
Sarà spiegato come realizzare un motore di ricerca basato su un database (che per comodità sarà chiamato motore I) e un motore basato su un servizio di IIS (motore II) (Index Server) che permette di indicizzare i files statici presenti nel proprio dominio.

Motore I - Il database
Il database da utilizzare è molto semplice e contiene una sola tabella:

I campi sono pochi e alcuni anche eliminabili, infatti se il motore di ricerca serve esclusivamente alla ricerca i campi come area, sezione possono anche essere eliminabili, inserendoli invece, possono, volendo, essere utilizzati anche per la ricerca.

Motore I - Inserimento url
Per inserire le pagine che possono essere ricercate nel motore è consigliabile utilizzare una maschera (o form) che permette l'inserimento delle nuova pagine ogni volta che risulta necessario... senza dover modificare il database ed effettuare nuovamente l'upload. Ecco il modulo che può essere facilmente modificato con l'inserimento o l'eliminazione di alcuni campi:

Area 
Sezione
Url
Titolo
Descrizione o Keywords
 

Se il proprio sito web ha un numero determinato di Aree principali è possibile realizzare un menu a tendina, come in questo caso, altrimenti è possibile mettere un semplice campo di testo.

Codice 12.1

<%tipo = Request.Form("tipo")If Trim(tipo) = "add" then'Connessione al databaseSet cn = Server.CreateObject("ADODB.Connection")cn.Open "provider=microsoft.jet.oledb.4.0;data source=" _& Server.MapPath("lez12_motore.mdb")Set rs = Server.CreateObject("ADODB.Recordset")rs.Open "url", cn, 3, 3rs.AddNewrs("area") = Trim(Request.Form("area"))rs("sezione") = Trim(Request.Form("sezione"))rs("url") = Trim(Request.Form("url"))rs("titolo") = Trim(Request.Form("titolo"))rs("descrizione") = Trim(Request.Form("descrizione"))rs.Updaters.Closeset rs = Nothingcn.Close set cn = NothingEnd if%><html><head><title>Inserimento pagina web</title></head><body><form method="POST" action="lez12_1_ins.asp"><div align="center"><center><table border="1" cellpadding="0" cellspacing="0" bordercolor="#111111" width="549" height="66"><tr><td width="189" height="1" bgcolor="#66CCFF"><b><font size="2" face="Verdana">Area</font></b></td><td width="354" height="1" bgcolor="#CCFFFF"><select size="1" name="area"><option>Asp</option><option>Php</option><option>WebMarketing</option><option>Approfondimenti</option></select></td></tr><tr><td width="189" height="16" bgcolor="#66CCFF"><b><font size="2" face="Verdana">Sezione</font></b></td><td width="354" height="16" bgcolor="#CCFFFF"><input type="text" name="sezione" size="22"></td></tr><tr><td width="189" height="10" bgcolor="#66CCFF"><b><font size="2" face="Verdana">Url</font></b></td><td width="354" height="10" bgcolor="#CCFFFF"><input type="text" name="url" size="46"></td></tr><tr><td width="189" height="9" bgcolor="#66CCFF"><b><font size="2" face="Verdana">Titolo</font></b></td><td width="354" height="9" bgcolor="#CCFFFF"><input type="text" name="titolo" size="29"></td></tr><tr><td width="189" height="10" bgcolor="#66CCFF"><b><font size="2" face="Verdana">Descrizione o Keywords</font></b></td><td width="354" height="10" bgcolor="#CCFFFF"><input type="text" name="descrizione" size="38"></td></tr><tr><td width="549" height="1" colspan="2" bgcolor="#66CCFF"><p align="center"><input type="submit" value="Inserisci" name="B1"></td></tr></table></center></div><input type="hidden" name="tipo" value="add"></form></body></html>

Tutto questo codice comprende il modulo e lo script asp per l'inserimento:

<%tipo = Request.Form("tipo")If Trim(tipo) = "add" then'Connessione al databaseSet cn = Server.CreateObject("ADODB.Connection")cn.Open "provider=microsoft.jet.oledb.4.0;data source=" _& Server.MapPath("lez12_motore.mdb")Set rs = Server.CreateObject("ADODB.Recordset")rs.Open "url", cn, 3, 3rs.AddNewrs("area") = Trim(Request.Form("area"))rs("sezione") = Trim(Request.Form("sezione"))rs("url") = Trim(Request.Form("url"))rs("titolo") = Trim(Request.Form("titolo"))rs("descrizione") = Trim(Request.Form("descrizione"))rs.Updaters.Closeset rs = Nothingcn.Closeset cn = NothingEnd if%>

Viene controllato se il modulo è stato compilato o ancora no, se lo è stato vengono creati i due oggetti Connection (cn) e RecordSet (rs), infine viene creato il record (rs.AddNew), inseriti i campi e viene chiuso tutto per liberare la memoria.

Motore I - La ricerca
Per effettuare la ricerca all'interno del database è necessario un form con un campo di testo e un bottone.

Cerca">

 

All'interno del campo di testo mettiamo un Request.Form("nomecampo"), in modo che quando vengono visualizzati i risultati nella stessa pagina nel campo di testo appare la parola cercata.

Codice 12.2

<html><head><title>Inserimento pagina web</title></head><body><form method="POST" action="lez12_1_cerca.asp"><div align="center"><center><table border="1" cellpadding="0" cellspacing="0" bordercolor="#111111" width="291" height="36"><tr><td width="189" height="16" bgcolor="#66CCFF"><b><font face="Verdana" size="2">Cerca</font></b></td><td width="161" height="16" bgcolor="#CCFFFF"><input type="text" name="cerca" size="22" value="<%=Request.Form("cerca")%>"></td></tr><tr><td width="356" height="1" colspan="2" bgcolor="#66CCFF"><p align="center"><input type="submit" value="Cerca &gt;&gt;&gt;" name="B1"></td></tr></table></center></div><input type="hidden" name="tipo" value="cerca"></form><br><br><ul><%tipo = Request.Form("tipo")If Trim(tipo) = "cerca" then'Connessione al databaseSet cn = Server.CreateObject("ADODB.Connection")cn.Open "provider=microsoft.jet.oledb.4.0;data source=" &_ Server.MapPath("lez12_motore.mdb")'Parola da cercarecerca = Request.Form("cerca")SQL = "SELECT * FROM url WHERE (titolo LIKE '%" & cerca &_ "%' OR descrizione LIKE '%" & cerca & "%') ORDER by titolo"Set rs = Server.CreateObject("ADODB.Recordset")rs.Open sql, cn, 3, 3If NOT rs.Eof AND Trim(cerca) <> "" thenWhile NOT rs.EOF%><li><a href="<%=Rs("url")%>"><%=rs("titolo")%></a></li><%rs.MoveNextWendElseResponse.Write("Pagina non trovata")End Ifrs.Closeset rs = Nothingcn.Close set cn = NothingEnd if%></body></html>

Lo script che permette la ricerca è molto semplice:

<%tipo = Request.Form("tipo")If Trim(tipo) = "cerca" then'Connessione al databaseSet cn = Server.CreateObject("ADODB.Connection")cn.Open "provider=microsoft.jet.oledb.4.0;data source=" &_ Server.MapPath("lez12_motore.mdb")'Parola da cercarecerca = Request.Form("cerca")SQL = "SELECT * FROM url WHERE (titolo LIKE '%" & cerca &_ "%' OR descrizione LIKE '%" & cerca & "%') ORDER by titolo"Set rs = Server.CreateObject("ADODB.Recordset")rs.Open sql, cn, 3, 3If NOT rs.Eof AND Trim(cerca) <> "" thenWhile NOT rs.EOF%><li><a href="<%=Rs("url")%>"><%=rs("titolo")%></a></li><%rs.MoveNextWendElseResponse.Write("Pagina non trovata")End Ifrs.Closeset rs = Nothingcn.Closeset cn = NothingEnd if%>

Viene utilizzata una query SQL

SQL = "SELECT * FROM url WHERE (titolo LIKE '%" & cerca & "%' OR descrizione LIKE '%" & cerca & "%') ORDER by titolo"

che fa una Select utilizzando l'istruzione SQL LIKE.

SELECT * FROM url WHERE

Con questa istruzione diciamo che deve fare una selezione di tutti i record (SELECT *) dalla tabella URL (FROM url) dove... ed ora viene specificato come fare la ricerca:

(titolo LIKE '%" & cerca & "%' OR descrizione LIKE '%" & cerca & "%')

L'istruzione LIKE permette l'utilizzo del carattere jolli '%' molto importante. Infatti utilizzando LIKE possiamo dire di cercare una parola che è contenuta in un campo mettendo questa parola tra due carattere jolli '%parola%', oppure sempre con LIKE è possibile cercare tutti i campi il cui titolo inizia con la a in questo modo: 'a%'. Esempio:

Nel database è presente un record con il campo titolo che contiene la seguente stringa: "ASP: Impaginazione articolo", e nella ricerca vogliamo cercare la parola "pagina", utilizzando la query:

SQL = "SELECT * FROM url WHERE titolo LIKE '%pagina%' ORDER by titolo"

Ci verrà segnalato il record "ASP: Impaginazione articolo", invece utilizzando la semplice stringa:

SQL = "SELECT * FROM url WHERE titolo = 'pagina' ORDER by titolo"

Non ci verrà dato alcun risultato in quanto in questo modo si richiede che il campo titolo contenga esclusivamente la parola 'pagina'.

Quindi con:

(titolo LIKE '%" & cerca & "%' OR descrizione LIKE '%" & cerca & "%')

viene ricercata la parola sia nel campo titolo sia nel campo descrizione, utilizzando come operatore OR in quanto è importante che la parola sia contenuta almeno in uno di questi 2 campi.

If NOT rs.Eof AND Trim(cerca) <> "" thenWhile NOT rs.EOF%><li><a href="<%=Rs("url")%>"><%=rs("titolo")%></a></li><%rs.MoveNextWendElseResponse.Write("Pagina non trovata")End If

Questo codice infine visualizza la ricerca se è stato trovato un risultato e se la parola cercata è diversa dallo spazio, attraverso l'utilizzo di un ciclo While, se la ricerca è fallita o si è tentato di cercare nulla si viene avvisati. E' possibile aggiungere un semplice controllo che garantisce l'inserimento di almeno x caratteri (consigliati tre) utilizzando la funzione Len:

If NOT rs.Eof AND Trim(cerca) <> "" AND Len(cerca) > 3 then...

Questo sistema è consigliato per database con al massimo poche migliaia di record (e comunque il controllo della lunghezza della parola da cercare è obbligatorio) in quanto richiede molte risorse di sistema per scandagliare molti record.

Motore II - La ricerca
Con l'utilizzo dell' Index Server (solitamente il servizio viene fatto pagare come accessorio addizionale) si risparmia il lavoro di inserimento manuale nel database, in quanto questo sistema non effettua una ricerca su database ma all'interno delle directory del proprio sito web (come Cerca in Windows). Tale servizio è molto potente e permette di ottenere anche un molte informazioni sui file. Per effettuare la ricerca è necessario impostare alcuni parametri:

<%    Dim sSearchString    Dim oQuery    cerca = Request.Form("cerca")    Const CATALOGO = "nome_index"    Set oQuery = Server.CreateObject("IXSSO.Query")    oQuery.Catalog = CATALOGO ' Nome del catalogo memorizzato inizialmente nella costante CATALOGO    oQuery.Query = "@all " & cerca & " AND NOT #path *_* AND NOT #path *downloads* AND NOT #path *images* AND NOT #filename *.class AND NOT #filename *.asa AND NOT #filename *.css AND NOT #filename *postinfo.html"    oQuery.MaxRecords = 200 ' Numero massimo di pagine cercate da visualizzare    oQuery.SortBy = "rank[d]" ' Indica in base a quale parametro devono essere visualizzati in ordine i risultati    oQuery.Columns = "DocAuthor, vpath, doctitle, FileName, Path, Write, Size, Rank, Create, Characterization, DocCategory" ' Indica le informazioni da prendere per ogni risultato.    Set oRS = oQuery.CreateRecordSet("nonsequential") ' Creazione del recordset    If oRS.EOF Then    Response.Write "Nessuna pagina trovata per la query: <i>" & sSearchString & "</i>"    Else    Do While Not oRS.EOF    Response.write "<b>Nome file:</b> " & oRS("FileName") & "<br>"    Response.write "<b>Titolo documento:</b> " & oRS("doctitle") & "<br>"    Response.write "<b>Peso:</b> " & oRS("Size") & "<br>"    Response.write "<b>Creato il:</b> " & oRS("Create") & "<br>"    Response.write "<b>Scritto:</b> " & oRS("Write") & "<br>"    Response.write "<b>Descrizione:</b> " & oRS("Characterization") & "<hr>"    oRS.MoveNext    Loop    End If    %>

La costante Catalogo è necessaria impostarla con il nome che viene fornito dall'amministratore del server.

La query:

oQuery.Query = "@all " & cerca & " AND NOT #path *_* AND NOT #path *downloads* AND NOT #path *images* AND NOT #filename *.class AND NOT #filename *.asa AND NOT #filename *.css AND NOT #filename *postinfo.html"

pur essendo molto lunga è semplice da comprende. Infatti viene richiesta l'indicizzazione di tutti i file (@all) cercando la stringa cerca tranne le pagine che hanno cartelle che contengono "_" o "downloads" o "images" o con nome file che hanno per estensione .class, .asa, .css o file che si chiamano postinfo.html. Tutte queste informazioni sono solo esempi, in quanto sono da impostare in base alle proprie esigenze e a come è stato strutturato il sito web. Vediamo ora gli altri parametri:

oQuery.MaxRecords
Permette di indicare il numero massimo di record da visualizzare

oQuery.SortBy
Indica per quale parametro devono essere ordinati i risultati. Rank[d] è il metodo migliore di ordinamento in quanto permette di ordinare in base all'attinenza della pagina con la stringa cercata.

oQuery.Columns
Permette di recuperare solo le informazioni necessarie, che sono:
DocAuthor, vpath, doctitle, FileName, Path, Write, Size, Rank, Create, Characterization, DocCategory

Infine il codice per la ricerca:

Set oRS = oQuery.CreateRecordSet("nonsequential") ' Creazione del recordset    If oRS.EOF Then    Response.Write "Nessuna pagina trovata per la query: <i>" & sSearchString & "</i>"    Else    Do While Not oRS.EOF    Response.write "<b>Nome file:</b> " & oRS("FileName") & "<br>"    Response.write "<b>Titolo documento:</b> " & oRS("doctitle") & "<br>"    Response.write "<b>Peso:</b> " & oRS("Size") & "<br>"    Response.write "<b>Creato il:</b> " & oRS("Create") & "<br>"    Response.write "<b>Scritto:</b> " & oRS("Write") & "<br>"    Response.write "<b>Descrizione:</b> " & oRS("Characterization") & "<hr>"    oRS.MoveNext    Loop    End If

Un normale ciclo While, e grazie all'utilizzo di Index Server è possibile visualizzare informazioni come nomefile, titolo, grandezza (peso), data di creazione, di modifica e altre caratteristiche comprese in (DocAuthor, vpath, doctitle, FileName, Path, Write, Size, Rank, Create, Characterization, DocCategory).