De man heeft een zoek-php-weergave. Veilig en gemakkelijk zoeken in mySQL. Een man van ver weg

Beknopte informatie over de zoekimplementatie: stringverwerking, uitsnijden van servicetekens, samenstellen van een databasequery, logica, pagina-uitvoer, relevantie.

Deel 1: Algemene uitspraken

Tekenreeksverwerking

Het eerste dat u hoeft te doen, is het touw met uw handen doorknippen.

$zoeken = substr($zoeken, 0, 64);

64 tekens zijn voldoende voor de gebruiker om te zoeken.

Laten we nu alle ‘abnormale’ symbolen met een heet strijkijzer uitbranden.

$search = preg_replace("/[^\w\x7F-\xFF\s]/", " ", $search);

In theorie zou je de gebruiker niet de kans moeten geven om te zoeken met te korte woorden; dit belast onder andere de server enorm. Laten we u dus toestaan ​​alleen te zoeken op woorden die langer zijn dan twee letters (als de limiet groter is, moet u “(1,2)” vervangen door “(1, aantal tekens)”).

$goed = trim(preg_replace("/\s(\S(1,2))\s/", " ", ereg_replace(" +", " "," $search ")));

En na het vervangen van slechte woorden, moet je dubbele spaties comprimeren (deze zijn speciaal gemaakt voor het correct zoeken naar korte woorden).

$goed = ereg_eplace(" +", " ", $goed);

Laten we zeggen dat we de gebruiker de mogelijkheid willen geven om de zoeklogica te kiezen: zoeken naar alle woorden of slechts één van meerdere woorden. Als je het wilt doen zoals in Yandex - twee ampersands betekenen "ik" (woord1&&woord2&&woord3) of iets anders, dan ben ik geen adviseur. Dwaasheid met snaren op een kleine site is imho de tijdsbesteding niet waard. Daarom tekenen we het zoekformulier als volgt:

zoek een van de woorden zoek alle woorden

En in het zoekscript controleren we nogmaals wat de gebruiker heeft ingevoerd:
Als (($logic!="AND") && ($logic!="OR"))

$logisch = "OF";

Hieronder ziet u hoe de logica zal worden gebruikt.

Zoekstatistieken

Het zou een goed idee zijn om de gebruiker onmiddellijk te laten weten hoeveel rijen van de tabel hij heeft gevonden. Hiervoor wordt een aanvullend verzoek aan de database gedaan:

$query = "SELECT id FROM tabel WHERE veld LIKE "%". str_replace(" ", "%" OR veld LIKE "%", $good). "%"";

Voor statistieken over afzonderlijke woorden kunt u het volgende doen:
$word = ontploffen(" ", $search); while (list($k, $v) = Each($word)) ( if (strlen($v)>2) $stat="$v:". mysql_num_rows(mysql_query("SELECT id FROM table WHERE field LIKE " %$v%"")); anders $stat="$v: kort"); $word_stats = "Woordstatistieken: ". implode("", $stat). "

"; uitgeschakeld($stat);

Welnu, als we eenmaal een zoekindeling en een aantal rijen met zoekresultaten hebben, is zoeken per pagina een fluitje van een cent.

We controleren de variabele $page (niet minder dan 0, niet meer dan $results_amount/$rows_in_page). In de query die het aantal rijen telt (zie hierboven), schrijven we de velden die we nodig hebben en de velden voor sortering. En dan voegen wij toe

If ($page==0) $request .= "LIMIT $rows_in_page"; anders $request .= "LIMIET ". $pagina*$rows_in_page. ","". $rijen_in_pagina;

(syntaxis: LIMIT of LIMIT , )

Als gevolg van het uitvoeren van een dergelijk verzoek ontvangen we precies dezelfde regels die op de pagina moeten worden weergegeven. Voor navigatie kunt u links naar de volgende en vorige pagina's tekenen, of, wat moeilijker is, een navigatie maken balk op meerdere pagina's. Als ($pagina>0) print (" vorige pagina

"); if ($pagina0 BESTEL OP relevante DESC

hoewel je kunt:

  • SELECT *, MATCH veld AGAINST ("$searchwords") als relev FROM tabel WHERE MATCH veld AGAINST ("$searchwords")>0 ORDER BY relev DESC
  • De snelheid is behoorlijk hoog - in sommige gevallen zelfs sneller dan zoeken
  • Al het bovenstaande werkt vanaf MySQL-versie 3.23.23

    Bij het maken van FULLTEXT-indexen voor meerdere velden zijn er 2 opties:

    CREATE TABLE tabel (veld1 VARCHAR (255), veld2 TEXT, FULLTEXT (veld1, veld2)) CREATE TABLE tabel (veld1 VARCHAR (255), veld2 TEXT, FULLTEXT (veld1), FULLTEXT (veld2))

    In het eerste geval is de volgende vraag mogelijk:

    SELECT *, MATCH veld1, veld2 AGAINST ("$searchwords") als relev FROM tabel ORDER BY relev DESC

    De relevantie wordt voor alle velden tegelijk berekend. In het tweede geval zal een dergelijk verzoek een fout genereren. Hier berekenen we de relevantie als volgt:

    SELECT *, MATCH veld1 AGAINST ("$searchwords")+MATCH veld2 AGAINST ("$searchwords") als relev FROM tabel ORDER BY relev DESC

    De tweede optie is wat ingewikkelder bij zoekopdrachten, maar naar mijn mening is het beter, omdat de zoekflexibiliteit neemt toe - voor elk veld kunt u bijvoorbeeld een significantiecoëfficiënt instellen en bij het optellen van de relevantie van de velden deze met deze coëfficiënt vermenigvuldigen. Er wordt met "meer" gezocht naar de zoekterm in velden met een hogere coëfficiënt. Als we bijvoorbeeld zoeken op geïndexeerde pagina's van een bronnenmap, wordt het veld voor de paginanaam meestal ingesteld met een hogere coëfficiënt dan de velden met metabeschrijvingstags of trefwoorden.

    Deel 3: Relevantie-oefeningen

    Mysql> verander tabelartikela voeg fulltext toe (ztext); FOUT 1073: BLOB-kolom "ztext" kan niet worden gebruikt in de sleutelspecificatie met het gebruikte tabeltype mysql> verander tabelarticlea type=myisam; Query OK, 36 rijen beïnvloed (0,60 sec) Records: 36 Duplicaten: 0 Waarschuwingen: 0 mysql > tabelartikel wijzigena fulltext toevoegen(ztext); Query OK, 36 rijen beïnvloed (10,00 sec) Records: 36 Duplicaten: 0 Waarschuwingen: 0

    Tekstindexen kunnen alleen worden uitgevoerd op tabellen van het type MyISAM. Teksten worden uit de tabel gehaald en in het indexbestand gedumpt, en het volume van de database groeit. Wat betreft verzoeken. U kunt het relev-veld niet gebruiken in een WHERE-clausule:

    SELECT *, MATCH veld AGAINST ("$searchwords") als relev FROM tabel WHERE relev>0 ORDER BY relev DESC

    Hoewel je het volgende kunt doen:

    SELECT *, MATCH-veld AGAINST ("$searchwords") als relev FROM tabel WHERE MATCH-veld AGAINST ("$searchwords")>0 ORDER BY relev DESC

    Het berekende veld kan uiteraard niet worden gebruikt in WHERE volgens alle syntaxisregels, maar kan wel worden gebruikt in HAVING:

    SELECT *, MATCH veld AGAINST ("$searchwords") als relev FROM tabel HAVING relev>0 ORDER BY relev DESC

    Zoeken via MATCH, zoals Oleg schreef, gebeurt alleen op het hele woord. ...Je kunt echter alleen sorteren op relevantie en selecteren op LIKE (dit heeft uiteraard invloed op de prestaties, ik weet niet eens hoeveel).

    We verwijderen de voorwaarde “relev>0” en verlaten de sortering.

    De rest is hetzelfde als voorheen: we hakken de resulterende string af en veranderen deze in een query met verschillende LIKE-operatoren:

    SELECT *,MATCH veld AGAINST ("$searchwords") AS relev FROM tabel WHERE veld LIKE "%$word1%" OF veld LIKE "%$word2%" ORDER OP relev DESC, datumveld DESC

    Deel 4: Voortzetting van waar we mee begonnen zijn

    Ik vervolg het onderwerp zoeken, gesorteerd op relevantie, in de MySQL-database, waarmee ik in september ben begonnen.

    MySQL biedt in de nieuwste versies van de database de mogelijkheid om FULLTEXT-indexering en het MATCH-veld AGAINST-constructie te gebruiken voor zoeken in volledige tekst. Niet alle servers beschikken echter over de nieuwste versie van MySQL en niet alle hostingproviders willen de software updaten vanwege de systeembetrouwbaarheid.

    Ooit ging ik ervan uit dat een zoekopdracht gesorteerd op relevantie in meerdere zoekopdrachten zou moeten worden uitgevoerd, en daarom was het beter om dit helemaal niet uit te voeren. Gedachten dat de relevantie in de vraag zelf kon worden berekend, kwamen op afstand bij me op, maar ik was bang om me zo'n constructie voor te stellen.

    SELECT titel, datumformaat(materiaal_datum,"%e.%c.%y") AS datum1, IF(tekst zoals "%word1 woord2 woord3%", 3*10, 0) + IF(tekst LIKE "%word1%", 9, 0) + IF(tekst LIKE "%word2%", 9, 0) + IF(tekst LIKE "%word3%", 9, 0) AS relevantie FROM tabel WHERE tekst LIKE "%word1%" OF tekst LIKE " %word2%" OF tekst ZOALS "%word3%" ORDER OP relevantie DESC, material_date DESC

    Het ziet er verschrikkelijk uit, maar het werkt zelfs op oudere versies van MySQL.

    Ik heb geprobeerd de snelheid te vergelijken met deze vraag:

    SELECT titel, date_format(material_date,"%e.%c.%y") AS date1, MATCH tekst AGAINST("word1 word2 word3") AS relevantie UIT tabel WAAR tekst ZOALS "%word1%" OF tekst ZOALS "%word2% " OF tekst zoals "%word3%" ORDER OP relevantie DESC, material_date DESC

    Gemiddeld is de snelheid van een universele zoekopdracht de helft van die van een zoekopdracht waarbij nieuwe constructies worden gebruikt. Dat is heel logisch: hoe groter de veelzijdigheid, hoe groter de intensiteit van de hulpbronnen.

    Laten we proberen zo'n query automatisch te bouwen. We hebben de lange rij afgesneden, evenals alle onjuiste karakters en korte woorden. Laten we een verzoek tekenen.

    $query = "SELECT titel, date_format(material_date,"%e.%c.%y") AS date1, IF(tekst zoals "%". $good_words. "%", ". (substr_count($good_words, " " ) + 1). "*10, 0) + IF(tekst LIKE "%". str_replace(" ", "%", 9, 0) + IF(tekst LIKE "%", $good_words). "%", 9, 0) AS relevantie UIT tabel WHERE tekst LIKE "%". str_replace(" ", "%" OF tekst LIKE "%", $good_words "%" ORDER OP relevantie DESC, material_date DESC";

    Niet erg moeilijk. Voor de betrouwbaarheid en bescherming tegen overstromingen kunt u het aantal woorden in het verzoek beperken.

    Enkele aanvullingen op eerdere publicaties

    Het totale aantal rijen dat in de tabel is gevonden. Om zoekresultaten weer te geven, moet je natuurlijk de LIMIT-operator gebruiken (gebruik kant-en-klare functies om de vorming van deze parameter niet elke keer te schrijven). Als er geen groeperingsbewerkingen worden uitgevoerd in de query, is het beter om het aantal rijen onmiddellijk in de query te tellen - COUNT(*), en niet via de php-functie mysql_num_rows(). Je kunt het controleren op grote tafels. Als er groepsbewerkingen worden uitgevoerd, maken we een query met COUNT(DISTINCT()), maar zonder GROUP BY.

    Achtergrondverlichting. Als er geen html-tags in de teksten staan, is het leven gemakkelijker

    Als er tags in de tekst worden gebruikt, zijn er drie opties: a) niet markeren b) omdat de gebruiker de tags niet ziet (tenzij een zeer nieuwsgierige gebruiker), dan kun je een indexveld maken waarin er geen tags, maar de symbolen [^\w\x7F-\xFF\s] worden vervangen door spaties (deze tekens worden helemaal aan het begin uit de zoekreeks verwijderd, zodat er niet naar wordt gezocht). In dit geval moet het zoeken en markeren worden gedaan met behulp van de index. c) tekst uit een gewoon veld markeren, nadat u eerder de tags hebt verwijderd met behulp van de functie srip_tags().

    De volledige versie van de zoekcode staat, zoals altijd, in de lijst met bestanden.




    Als u nog andere vragen heeft of iets niet duidelijk is, welkom bij ons

    De beste manier om een ​​gebruiker op een site te houden, is door hem te laten vinden wat hij zoekt. Als u hiervoor een handig systeem creëert, zal de voorkeur voor uw site toenemen en zal de gebruiker zeker terugkomen om te ontdekken wat hem interesseert.

    Ik laat u zien hoe u een eenvoudig, maar functioneel effectief zoekformulier kunt maken dat wordt gebruikt om naar artikelen op de site te zoeken. De resultaten verschijnen zonder herladen op de pagina, wat ongetwijfeld de beste manier is om informatie te presenteren.

    Ik zal 2 bestanden maken: search.php, die HTML en JavaScript zullen bevatten. Het tweede bestand, do_search.php, zal de PHP-code bevatten. Laten we beginnen met het maken van het eerste bestand:

    PHP, jQuery zoekdemo $(function() ($(".search_button").click(function() ( // krijg wat de gebruiker heeft geschreven var searchString = $("#search_box").val(); // form a query string var data = "search="+ searchString; // if searchString is niet leeg if(searchString) ( // maak een ajax-verzoek $.ajax(( type: "POST", url: "do_search.php", data: data, beforeSend: function(html) ( // wordt uitgevoerd voordat het verzoek wordt aangeroepen $("#results").html(""); $("#searchresults").show(); $(". word").html (searchString); ), success: function(html)( // wordt uitgevoerd na ontvangst van de resultaten $("#results").show(); $("#results").append(html) ; ) ) retourneert onwaar ));
    Probeer het woord ajax in te voeren

    Resultaten voor

    In dit bestand hebben we een regulier HTML-formulier gemaakt dat een POST-verzoek naar de backend verzendt: het do_search.php-bestand.

    De PHP-code bevat commentaar, zodat u gemakkelijk kunt begrijpen hoe het script werkt. Als er overeenkomsten in de database zijn, toont u deze aan uw gebruiker, waarbij u de woorden waarnaar de gebruiker heeft gezocht vetgedrukt markeert.

    Body( lettertypefamilie:Arial, Helvetica, sans-serif; ) *( marge:0;opvulling:0; ) #container ( marge: 0 auto; breedte: 600px; ) a ( kleur:#DF3D82; tekstdecoratie: geen ) a:hover ( color:#DF3D82; tekstdecoratie:underline; ) ul.update ( list-style:none;font-size:1.1em; margin-top:10px ) ul.update li( height:30px; border-bottom:#dedede solid 1px; tekst-align:left;) ul.update li:first-child( border-top:#dedede solid 1px; hoogte:30px; text-align:left; ) #flash ( margin- top:20px; tekst-uitlijning:links;) #zoekresultaten (tekst-uitlijning:links; marge-top:20px; weergave:geen; lettertypefamilie:Arial, Helvetica, schreefloos; lettertypegrootte:16px; kleur: #000; ) .word ( lettertypegewicht:vet; kleur:#000000; ) #search_box (opvulling:4px; rand:vast 1px #666666; breedte:300px; hoogte:30px; lettertypegrootte:18px;-moz- border-radius: 6px;-webkit-border-radius: 6px; ) .search_button ( border:#000000 effen 1px; opvulling: 6px; kleur:#000; lettertype-gewicht:vet; lettergrootte:16px;-moz- randradius: 6px;-webkit-border-radius: 6px).found(lettertypegewicht: vet; lettertype: cursief; kleur: #ff0000; ) h2 (marge-rechts: 70px; )

    Je hebt dus geleerd hoe je een eenvoudig zoekformulier kunt maken dat werkt zonder de pagina opnieuw te laden. Ik hoop dat je de les leuk vond.

    Van de auteur: PHP-zoekscript is een integraal onderdeel van een moderne hulpbron. Maar voor beginnende ontwikkelaars kan de implementatie ervan een “hoeksteen” worden. Vandaag zal ik proberen de constructie van een dergelijke module zo eenvoudig mogelijk uit te leggen, zodat de code je niet bang maakt met zijn buitensporige complexiteit.

    Op zoek naar PHP

    Het organiseren van een intern zoeksysteem op een website is een belangrijke taak. De aanwezigheid van dergelijke functionaliteit verbetert de hulpbronnen aanzienlijk in de ogen van elke gebruiker. Dit geldt met name voor sites met een beperkt thema, waarvan de inhoud is gewijd aan het oplossen van specifieke “problemen”. Bijvoorbeeld bij webprogrammering.

    Om een ​​sitezoekscript in PHP te schrijven, is meestal een combinatie van deze programmataal met . AJAX-technologie wordt gebruikt om een ​​interactief zoeksysteem te implementeren. Maar vandaag zullen we niet in zulke wildernis "winden" en ons concentreren op de klassieke versie.

    Ik zal het eenvoudigste voorbeeld van een zoekopdracht geven. Er wordt niet gecontroleerd op de aanwezigheid van een verbinding met het DBMS, de resultaten van het geretourneerde monster worden niet gecontroleerd, enz. Al deze subtiliteiten kun je zelf toevoegen. Het doel van het materiaal is om een ​​algemeen idee te geven van het bouwen van een intern zoeksysteem op een moderne internetbron. Laten we gaan!

    Om te beginnen zal ik de code geven voor het formulier voor het invoeren van een zoekopdracht. Dit is een eenvoudige opmaak, zonder zelfs maar de geringste stilistische “franjes”.




    < form name = "f1" method = "post" action = "search.php" >

    < input type = "search" name = "search_q" / > < / br >

    < / br >

    < input type = "submit" value = "Zoekopdracht" / > < / br >

    < / form >

    Zo ziet het formulier eruit in de browser:

    Laten we naar het script gaan

    Laten we nu direct naar de programmacode gaan. Om te beginnen zal ik de structuur geven van de tabel die moet worden gemaakt in . We zoeken naar gepubliceerd materiaal op titel. Met hetzelfde principe kunt u een PHP-script maken voor het zoeken naar woorden op een site. Alles ligt in jouw bekwame handen.

    Eerst onderscheppen we de waarde die de gebruiker in het formulier heeft ingevoerd. Dan ruimen we het op van “rommel”: extra spaties, tags en connecteren met de database. Hierna voeren we een SQL-query uit waarin we de waarde van de zoekopdracht vergelijken met de naam van de materialen die in de tabel zijn opgeslagen. Als er een match is, tonen wij de bijbehorende inhoud. Aan het einde sluiten we de verbinding met MySQL en ‘resetten’ we het verzoek. Hier is de volledige voorbeeldcode: