Consigli organizzazione motore di ricerca

  • Creatore Discussione Creatore Discussione RedWolf
  • Data di inizio Data di inizio

RedWolf

Nuovo Utente
7 Mag 2009
22
0
0
Roma
www.antrocom.org
Vorrei implementare per il minisito che sto costruendo un motore di ricerca che interroghi il database mySQL. Prima di imbarcarmi nella programmazione, e magari pentirmi e dover rifare tutto, mi piacerebbe avere da voi un'opinione su alcune riflessioni...

Il database è strutturato in sei tabelle, in cui si ripete un campo uguale, in modo da rendere possibili eventuali join. Fondamentalmente si tratta di anagrafiche inserite in campi varchar o text. Non ho ancora provveduto però a indicizzare con fulltext.
Dico questo perchè pensavo di inserire un campo di ricerca libera in boolean mode, controllato da un'espressione regolare per evitare gli errori di battitura (es: voglio trovare "mario" e digito "nario" o ",ario" o "maro"...).

Qui il primo dubbio: praticamente sono possibili tutti gli errori di battitura immaginabili, mi conviene tirarmi scemo con una RegExp?

Visto che la ricerca fulltext non restitusce chiavi con meno di quattro lettere mentre nel DB ho sicuramente dati importanti di tre lettere sole), pensavo di aggiungere form che interrogano le singole tabelle.
Ad es., se le tabella sono "utente", "interessi", "azienda", pensavo fosse utile mettere tre ricerche separate che però si possono combinare insieme:

Cerca utente:
Cerca interesse:
Cerca Azienda:

Sarebbe sensato fare una ricerca di tipo "like", anche se meno veloce e affidabile della fulltext, ma a parte di nuovo il discorso della RegExp, mi domando se ciò non risulti pesante per la query.
Inoltre, meglio un join tra le tabelle, oppure estrapolare tre array e poi unirli?
Grazie per i suggerimenti che vorrete darmi! :)
 
Qui il primo dubbio: praticamente sono possibili tutti gli errori di battitura immaginabili, mi conviene tirarmi scemo con una RegExp?
No, tanto non potrai prevedere tutti gli errori possibili, neanche Google ci riesce.
Sarebbe sensato fare una ricerca di tipo "like", anche se meno veloce e affidabile della fulltext, ma a parte di nuovo il discorso della RegExp, mi domando se ciò non risulti pesante per la query.
Non mi preoccuperei tanto per il peso delle queries a meno che non pensi di generare tanto traffico e quindi molte queries simultanee; potresti utilizzare il Full text sopra le 4 lettere e Like sotto.
Inoltre, meglio un join tra le tabelle, oppure estrapolare tre array e poi unirli?
una join, con un'unica interrogazione ti risolvi il problema
 
Ultima modifica:
Grazie dei consigli, mi sento più sicuro! :)
Un'altra cosa ce mi è venuta in mente dopo aver scritto il post: forse per quel che devo fare è esagerato, ma come vedreste l'uso di Zend?
 
Sto completando il modulo di ricerca, ma ho dei problemi nella ricerca full text: le chiavi immesse nel form non sono sempre trovate. Riassumendo, ho sei tabelle: solo i dati di "utenti" sono obbligatori, mentre è facoltativo l'inserimento di valori nelle restanti cinque tabelle.
Per ogni tabella ho una ricerca con LIKE, funzionante, e poi la ricerca libera, full text, su tutte e sei le tabelle (in sostanza, cerco nell'intero database). Non capisco perchè, pur elencando tutti i campi delle tabelle e forzando la selezione di "username" dalla tabella "utenti", essendo l'unico campo comune a tutte le tabelle del DB, la query full text non mi restituisce valori che so essere presenti.

Ho ragionato così: estraggo tutti i dati dalla tabella utenti e li unisco con LEFT JOIN alle altre tabelle usando il campo username: nel contempo, forzo l'estrazione del campo utenti.username, in modo che non mi sovrascriva il dato con l'ultimo campo "username" trovato. In questo modo, anche se non c'è nulla nelle altre tabelle, visualizzo comunque i dati della tabella utenti, che so essere presenti.

Nello script sottostante la prima parte è la ricerca full text, la seconda è di tipo like, che allego solo per aiutare chi sta cercando codice di esempio nel forum! ;)

PHP:
if(isset($_POST['submit']))
{

// abbiamo premuto "invia", se sto facebdo una ricerca libera abbiamo una variabile
if($_POST['libera'] !="") {
$libera = $_POST['libera'];

// filtri per evitare brutte sorprese
$libera = strtoupper($libera);
$libera = strip_tags($libera);
$libera = trim ($libera);

$testo = htmlspecialchars(addslashes($_POST["libera"]));

//Adesso estraggo i dati dal DB e li confronto con match e against per vedere se la chiave di ricerca è presente.

        $sql = "SELECT *, utenti.username
        FROM utenti
        LEFT JOIN settore USING (username)
        LEFT JOIN ricerca USING (username)
        LEFT JOIN posizione USING (username)
        LEFT JOIN info USING (username)
        LEFT JOIN enti USING (username)
        WHERE MATCH(utenti.nome, utenti.cognome, utenti.username, utenti.ragsociale, utenti.luogo, utenti.area, settore.username, settore.settore, settore.nuovo, ricerca.username, ricerca.insegnamenti, ricerca.ricerca, ricerca.pubblicazioni, posizione.username, posizione.ente, posizione.facolta, posizione.dipartimento, posizione.sezione, posizione.laboratorio, posizione.ufficio, posizione.ruolo, posizione.regione, info.username, info.membro, info.commenti, info.didascalia, enti.username, enti.nomeente, enti.tipo, enti.nuovotipo, enti.descrizione) AGAINST ('$testo' IN BOOLEAN MODE);";

        // se la chiave non c'è, avvisiamo a video, altrimenti elenchiamo l'utente associato alla chiave di ricerca stessa.
        $query = mysql_query($sql);
        $quanti = mysql_num_rows($query);
        if ($quanti == 0)
        {
             echo "Spiacenti, la ricerca di '$libera' non ha prodotto risultati. Riprovare con altri termini.
             ";
        }
        else
        {

        echo "
        Utenti compatibili con i termini di ricerca '$libera':";


                while ($rs = mysql_fetch_array($query)) {
                $id = $rs[id];
                $nome = $rs[nome];
                $cognome = $rs[cognome];
                $username = $rs[username];

                $soggetto=urlencode($username);
                echo "$cognome $nome $username";

            }

        }
    }

////////////////////////
// Ora utilizziamo una ricerca di tipo LIKE sulle singole tabelle del DB:
////////////////////////

if($_POST['utente'] !="") {
$utente = $_POST['utente'];

// Filtri per evitare brutte sorprese
$utente = strtoupper($utente);
$utente = strip_tags($utente);
$utente = trim ($utente);

//Cerchiamo la chiave nella tabella del DB

    $testo = htmlspecialchars(addslashes($_POST["utente"]));

        $arr_txt = explode(" ", $testo);
        $sql = "SELECT *, utenti.username FROM utenti LEFT JOIN info ON utenti.username=info.username WHERE ";
        for ($i=0; $i<count($arr_txt); $i++)
        {
            if ($i > 0)
            {
                $sql .= " AND ";
            }
            $sql .= "(utenti.nome LIKE '%" . $arr_txt[$i] . "%' OR utenti.cognome LIKE '%" . $arr_txt[$i] . "%' OR utenti.username LIKE '%" . $arr_txt[$i] . "%' OR info.didascalia LIKE '%" . $arr_txt[$i] . "%')";
        }
        $sql .= " ORDER BY utenti.username DESC";
        $query = mysql_query($sql);
        $quanti = mysql_num_rows($query);
        if ($quanti == 0)
        {
             echo "Spiacenti, la ricerca di '$utente' non ha prodotto risultati. Riprovare con altri termini.";

             }
        else
        {

        echo "
        Utenti compatibili con i termini di ricerca '$utente':";

            for($x=0; $x<$quanti; $x++)
            {
                $rs = mysql_fetch_row($query);
                $id = $rs[0];
                $nome = $rs[1];
                $cognome = $rs[2];
                $username = $rs[3];

                $soggetto=urlencode($username);
                echo "$cognome $nome $username";

            }
        }
    }
}
 

Discussioni simili