• User Attivo

    SQL: problema motore di ricerca

    Buonasera a tutti, avrei un problema con un motore di ricerca interno al mio sito.

    Usando la funzione LIKE '%valore% se $valore="foto di macchine" mi trova le righe che corrispondono a quelle parole messe in quel dato ordine.

    Io vorrei sapere come fare per fare in modo che l'operazione trovi le righe che contengono le 3 parole indipendentemente dalla loro posizione.

    Per spiegarmi meglio se ho questa riga in un campo:

    "foto di diverse macchine da corsa"

    e nel motore di ricerca viene inserito "foto macchine" mi trovi comunque anche quella riga nonostante non abbia le due parole una dietro l'altra.

    Grazie dell'aiuto 🙂


  • User Attivo

    Come sql devi scrivere LIKE '%foto%' AND LIKE '%macchine%'
    In PHP è sufficiente che esplodi la stringa di input e fai un ciclo in cui aggiungi gli AND LIKE.
    Chiedi se ti serve il codice!


  • User Attivo

    @Raiken said:

    Buonasera a tutti, avrei un problema con un motore di ricerca interno al mio sito.

    Usando la funzione LIKE '%valore% se $valore="foto di macchine" mi trova le righe che corrispondono a quelle parole messe in quel dato ordine.

    Io vorrei sapere come fare per fare in modo che l'operazione trovi le righe che contengono le 3 parole indipendentemente dalla loro posizione.

    Per spiegarmi meglio se ho questa riga in un campo:

    "foto di diverse macchine da corsa"

    e nel motore di ricerca viene inserito "foto macchine" mi trovi comunque anche quella riga nonostante non abbia le due parole una dietro l'altra.

    Grazie dell'aiuto 🙂

    Dovrebbe essere una cosa di questo tipo:
    SELECT *
    FROM nometabella
    WHERE nome LIKE '%foto%macchine%'
    OR nome LIKE '%macchine%foto%'


  • User Attivo

    problema risolto, grazie dell'aiuto 😉

    ecco il codice corretto di seguito:

    
    //divido per parole
    $parole=explode(" ",$descrizione);
    //parte il conto parole
    $count=0;
    //faccio partire il ciclo per ogni parola della stringa
    foreach ($parole AS $parola)
    {
    //se è il primo valore metto LIKE
    if($count==0){
    //aggiungo il valore alla stringa
    $stringa_ricerca=$stringa_ricerca."LIKE '%$parola";
    }
    else{
    $stringa_ricerca=$stringa_ricerca."%$parola";
    }
    //numero della parola
    $count=++$count;
    }
    $stringa_ricerca="description ".$stringa_ricerca."%' or name ".$stringa_ricerca."%'";
    
    

  • User Attivo

    @Raiken said:

    problema risolto, grazie dell'aiuto 😉

    ecco il codice corretto di seguito:

    >
    //divido per parole
    $parole=explode(" ",$descrizione);
    //parte il conto parole
    $count=0;
    //faccio partire il ciclo per ogni parola della stringa
    foreach ($parole AS $parola)
    {
    //se è il primo valore metto LIKE
    if($count==0){
    //aggiungo il valore alla stringa
    $stringa_ricerca=$stringa_ricerca."LIKE '%$parola";
    }
    else{
    $stringa_ricerca=$stringa_ricerca."%$parola";
    }
    //numero della parola
    $count=++$count;
    }
    $stringa_ricerca="description ".$stringa_ricerca."%' or name ".$stringa_ricerca."%'";
    
    >```
    
    è che così con una ricerca "test prova", traverai i campi che contengono "test di qualcosa prova", ma non "prova di qualcosa test". O sbaglio?
    
    intanto che ci sei, potresti convertire il tuo database in myisam, se già non lo è, e fare una ricerca su un indice fulltext.
    
    Spiegazione breve: http://www.risorse.net/mysql/query_full_text.asp 
    Se ti piace leggere: http://php.html.it/articoli/leggi/898/un-motore-di-ricerca-in-php-e-mysql/2/

  • User Attivo

    grazie del consiglio, effettivamente succede come hai detto tu.

    ho letto le due guide e ho provato a fare questo codice:

    
    
    //divido per parole
    $parole=explode(" ",$descrizione);
    //parte il conto parole
    $count=0;
    //faccio partire il ciclo per ogni parola della stringa
    foreach ($parole AS $parola)
    {
    //se è il primo valore metto apro gli apici
    if($count==0){
    //aggiungo il valore alla stringa
    $stringa_ricerca=$stringa_ricerca."'$parola";
    }
    else{
    $stringa_ricerca=$stringa_ricerca.",$parola";
    }
    //numero della parola
    $count=++$count;
    }
    //definisco la porzione della query
    $stringa_ricerca="match (name,description) against ($stringa_ricerca')";
    
    
    

    e questa query

    
    
    $query_search_foto=mysql_db_query($database_photo,"select *, ($stringa_ricerca) as score from photo where ($stringa_ricerca) order by score DESC limit $start,10",$db);
    
    
    

    ma non dà i risultati sperati.

    Quando faccio una richiesta di due parole la variabile $strimga_query diventa:

    match (name,description) against ('3,febbraio,concerto')

    per come ho impostato il codice, quindi da questo punto sembrerebbe giusto anche perchè se la facessi diventare:

    match (name,description) against ('3','febbraio','concerto')

    mi darebbe errore.


  • User Attivo

    Per avere i risultati sperati (se ho immaginato giusto a cosa speri tu :P) devi usare gli operatori boleani per dire "trova se c'è la parola1 AND la parola N", altrimenti come hai fatto tu cerca parola1 OR parolaN. Questa ad esempio funziona (ho cambiato tabella e colonne di ricerca):

    SELECT *, MATCH (post_title, post_content) 
    **AGAINST ('+test +di +prova' IN BOOLEAN MODE) AS score **
    FROM **wp_posts** 
    WHERE MATCH (post_title, post_content) 
    AGAINST ('+test +di +prova' IN BOOLEAN MODE) 
    ORDER BY score DESC limit 1, 10
    

    Quindi se non vuoi introdurre ricerche avanzate, potresti fare così:

    [php]// D'esempio
    $start = 1;
    $descrizione = 'brebei mario';

    // Solo le parole
    preg_match_all('/\w+/', $descrizione, $stringa_ricerca);

    // Se parole
    if($stringa_ricerca[0]){

    $stringa_ricerca = "MATCH (post_title, post_content) AGAINST ('+" .implode(' +', $stringa_ricerca[0]) ."' IN BOOLEAN MODE)";

    // La tua query:
    echo "SELECT *, $stringa_ricerca AS score FROM wp_posts WHERE $stringa_ricerca ORDER BY score DESC LIMIT $start, 10";
    }[/php]


  • User Attivo

    Ho messo il tuo codice, ma ancora i risultati sono mischiati.

    Per dire, faccio la ricerca con la chiave "3 febbraio", mi trova il primo risultato che contiene la chiave "3 febbraio" poi mi trova tutti i risultati con "2 Febbraio" e poi di nuovo tutti i restanti che hanno "3 febbraio".

    Assurdo :arrabbiato:


  • User Attivo

    Hai ragione! Non riuscivo a capire perché ieri funzionava, oggi no. Poi ho notato che con alcune ricerca funziona ed altre no. La soluzione è nel manuale 😄

    http://dev.mysql.com/doc/refman/5.0/en/fulltext-fine-tuning.html

    The minimum and maximum lengths of words to be indexed are defined by the ft_min_word_len and ft_max_word_len system variables. (See Section 5.2.3, “System Variables”.) The default minimum value is four characters; the default maximum is version dependent. If you change either value, you must rebuild your FULLTEXT indexes. For example, if you want three-character words to be searchable, you can set the ft_min_word_len variable by putting the following lines in an option file: [mysqld]
    ft_min_word_len=3
    Then you must restart the server and rebuild your FULLTEXT indexes. Note particularly the remarks regarding myisamchk in the instructions following this list.

    In pratica, di default, la ricerca non considera parole più corte di 4 caratteri 😛

    Nota anche che in boolean mode lo score è ininfluente, perché il valore è 1 o 0.


  • User Attivo

    che peccato 😛

    lascerò così allora è già comunque un passo avanti.

    Grazie dell'aiuto e per la pazienza 😄