Avatar billede Mik2000 Professor
18. januar 2010 - 23:45 Der er 15 kommentarer og
1 løsning

Søgefunktion - mangler lidt hjælp

Hej

Jeg er ved at lave en søgefunktion der søger i en database. Det er der ingen problemer med.

Problemet er at jeg gerne vil have at man ligesom på f.eks. Google kan sætte "" rundt om ord for at søge eksakt på en sætning (jeg har bare valgt at bruge * i stedet for "), og lign. muligheder.

Problemet er så følgende:
Når jeg har hentet feltet, hvordan tjekker jeg så om der er sat ** rundt om nogle ord, og hvordan finder jeg ud af hilke ord der er det omkring, så jeg kan sætte det ind i sql mv (som jeg godt ved hvordan man gør).

Ligeledes vil jeg også gerne kunne søge på en del af et ord ved at skrive ... (3 punktumer) foran eller efter ordet for at angive der kan komme mere. Men igen, hvordan finder jeg ud af om folk har gjort det, og hvilket ord der er tilknyttet

Håber det er til at forstå, ellers så spørg endelig.

På forhånd tak
Avatar billede Slettet bruger
19. januar 2010 - 09:06 #1
Det er absurd at lave om på globalt indarbejdede kontrol-tegn:
" " indrammer en eksakt sætning og * er joker - sådan ER det bare.

Når det er sagt, så er det vel bare et spørgsmål om at indsætte en "input-vasker"

Der plukker de endelige søgeord ud af den streng brugeren sender:
FINDES der et " ?
- hvis ja, er der et mere ?
  - hvis ja, så fisk strengen imellem de to, ud og gem den, og gentag med resten
  - hvis nej, er der en "fejl"

NB: Google understøtter faktisk ikke * - modsat hvad mange tror...
- den kan kun finde hele ord (eller varianter)
- ikke sammesatte (bruges ikke ret meget på engelsk)
Eksempel: kufferthåndtag - findes IKKE ved søgning efter kufferth*
Avatar billede Mik2000 Professor
19. januar 2010 - 09:40 #2
Hej

Grunden til jeg vi ændre det var at " ofte bliver anset som et problemtegn grundet det buges til de ting det gør i PHP. Men er dybest set ligemeget.

Mendet jeg søger er hvordan dette rent praktisk gøres i PHP:
-FINDES der et " ?
- hvis ja, er der et mere ?
- hvis ja, så fisk strengen imellem de to, ud og gem den, og gentag med resten
- hvis nej, er der en "fejl"
Avatar billede Slettet bruger
19. januar 2010 - 20:49 #3
Avatar billede Mik2000 Professor
19. januar 2010 - 21:49 #4
Aaah ja selvfølgelig.....

-------------------------------
Hvis man så har en sætning som f.eks.:

$string = 'Hund #hunde er søde# hundekurv';
Så benytter man understående til at finde den første #
$nr = strpos($string , '#');

Men hvordan finder man så resten af dem. Er det noget med bare at smide dem i en while løkke

-------------------------------

Og hvis man så har en sætning som denne
$string = "Hund *hunde er søde hundekurv";
Så finder man position på stjerne sådan
$nr = strpos($string , "*");

Men hvordan får man så resten af ordet ud i en variabel dvs. hunde og hvordan tjekker man om stjernen er foran eller bagved det pågædende ord?

-------------------------------

Puha det var noget - men håber du/I forstår og kan hjælpe :)
Avatar billede Slettet bruger
20. januar 2010 - 09:20 #5
strpos kan kaldes med en 3. parameter (offset) som angiver hvorFRA der skal søges efter "nålen" - altså springe de første x tegn over. På den måde kan man arbejde sig igennem strengen, bid for bid.

------------------------

Der er ingen facit-liste. Whatever works (well). Programmering er en kunstart!

En måde kunne være at søge efter mellemrum - det som ikke er mellemrum, er bogstaver (eller tegn i hvertfald). Det som ligger imellem sidste mellemrum og stjernen...

En anden fundamental teknik du også bør kende til er arrays, som gør det lettere at arbejde med information i "bidder" - som f.eks. de enkelte ord i en sætning.
Der findes en dejligt dramatisk navngivet funktion: explode
http://dk.php.net/manual/en/function.explode.php

------------------------

Husk at disse php-manual-sider indeholder, foruden selve definitionen af funktionerne, indeholder bunker af eksempler og løsninger på almindelige problemer, nederst. Rigtig gode at blive klog af!
Avatar billede CCodam Nybegynder
20. januar 2010 - 09:52 #6
Jeg vil foreslå at starte ud med at bruge preg_split, som benytter sig af regular expression til at opdele din string.

Det er dog ikke lige til, hvis man ikke forstår sig på regular expressions :/ Her er hvad jeg mener burde opfylde dit behov:

$search_string = "Hund* \"hunde er søde\" *kurv 'dalmatinere er de bedste' bla bla";

$words = preg_split("/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|" . "[\s,]*'([^']+)'[\s,]*|" . "[\s,]+/", $search_string, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);



Dette vil lave et array som ser ud som følgende:

Array
(
    [0] => Hund*
    [1] => hunde er søde
    [2] => *kurv
    [3] => dalmatinere er de bedste
    [4] => bla
    [5] => bla
)



Herefter kan du så tjekke for speciel tegnene * m.m. på følgende måde:

foreach ( $words as $value )
{
  if (substr($value, 0, 1) == "*")
  {
    //kode der skal eksekveres ved * foran ordet
    echo substr($value, 1) . "<br />"; //udskriver ordet uden *
  }
  else if (substr($value, -1, 1) == "*")
  {
    //kode der skal eksekveres ved * bagpå ordet
    echo substr($value, 0, -1) . "<br />"; //udskriver ordet uden *
  }
  else
  {
    //kode der skal eksekveres ved normale ord eller sætninger
    echo $value . "<br />"; //udskriver ordet
  }
}



Du er velkommen til at benytte siden www.whattheflux.dk/test , hvor du kan afvikle php kode "on the fly" :)
Avatar billede gbjensen65 Nybegynder
20. januar 2010 - 22:21 #7
En ting jeg godt kunne tænke mig at vide her, er hvor mange felter skal du søge i og har du evt. data fordelt over flere tabeller ?

for så skal du bruge en MySql Fulltext search funtion, du kan se mere her: http://dev.mysql.com/doc/refman/5.1/en/fulltext-search.html

Det giver dig muligheder for at søge efter ord, sætninger og kombinationer at ord der skal findes og evt. ikke skal findes.

Du kan prøve hvordan det virker her:http://goodbeer.dk/find.php?seeq=%22Carlsberg%20Porter%22
Som du kan se, så kan brugeren selv vælge hvor der skal søges og om der skal søges efter en sætning, ord eller kombinationer
Det er en funktion som jeg har skrevet over fulltext.
Der er kun en beklagelig begrænsning, den er desværre ikke glad for at finde korte ord på under 3 tegn.

Jeg hjælper dig gerne videre hvis du har brug for det.
Avatar billede Mik2000 Professor
23. januar 2010 - 22:14 #8
CCodam - det ser ud til at virke fint :)
Så der er point :)

Så laver jeg så den søger med et OR mellem hvert ord.

Så vil jeg lave det sådan at hvis de skriver AND mellem nogle ord, så skal begge de 2 være med.
Men i din løsning er det vel bare at sige
if ($value == "AND") {
  // og så her tage ordet før og efter
}

Eller kan man også få den til at samle ordet sådan at hvis der er AND kommer både ordet/sætningen før og efter AND med så det bliver til "et ord"?
... kan man det med regular expressions også?
Avatar billede Mik2000 Professor
24. januar 2010 - 03:43 #9
Jeg har kigget lidt på det, men hvordan laver man det sikkert, når de skal have lov at benytte "" tegn - det åbner jo op for de kan manipulerer med egen sql - gør det ikke?
Avatar billede Mik2000 Professor
24. januar 2010 - 03:43 #10
(hvis det er noget der skal generere en SQL sætning)
Avatar billede gbjensen65 Nybegynder
24. januar 2010 - 12:55 #11
Hej mik2000,

Nej det giver ikke mulighed for at nogen kan indsætte sql kommandoer og gøre noget ved din database, men hvis jeg skulle tage fejl, så kan du jo blackliste en række ord som alle er sql kommandoer, som select, insert, alter, change, modify og drop.
Jeg har forsøgt om en SQL query indtastet skulle give et andet resultat, men den søger efter ordene, udfører ikke den ekstra søgning. Så jeg tror ikke at det er en sikkerheds risiko.

Her er der et eks. på en freetext MySql query:
$sql="SELECT *, MATCH (emne,text,username) AGAINST ('".$seeqit."' IN BOOLEAN MODE) AS score FROM news WHERE MATCH (emne,text,username) AGAINST ('".$seeqit."' IN BOOLEAN MODE)";
Den søger i den indexerede tabel news, i felterne emne, text og username. De ord som der søges efter skal forekomme i en eller flere af felterne for at give et positivt hit.

Fordelen ved at søge direkte i databasen, er at du kun behøver at indlæse de linier fra databasen, hvor der er et positivt hit, og ikke hele tabellen, for derefter at søge med et PHP script.
Hvis du har mange linier, så tager det tid!

Hvis du vil søge på tværs af flere tabeller så bør du oprette en ny søge tabel, som er en kopi af indholdet af de tabeller som skal kombineres, det kan ligges ind som et cron job og udføres automatisk f.eks. 1 gang hver nat.
Avatar billede gbjensen65 Nybegynder
27. januar 2010 - 17:07 #12
Har du brug for mere hjælp ?
Avatar billede Mik2000 Professor
27. januar 2010 - 22:30 #13
Tror det virker efterhånden
Jeg har brugt det fra CCodam

Det eneste jeg lidt mangler er hvordan man kan tilføje i koden:
$words = preg_split("/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|" . "[\s,]*'([^']+)'[\s,]*|" . "[\s,]+/", $search_string, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);

Således at hvis der står AND i et af ordene, så skal den tage ordet før og ordet efter, og sætte sammen med det.
Sådan at hvis man skriver:
søgeord1 søgeord2 "søgesætning der søges på" søgeord3 AND søgeord4 søgeord5 "søgesætning 2 der søges på" AND søgeord6 søgeord7

så bliver det til
søgeord1
søgeord2
"søgesætning der søges på"
søgeord3 AND søgeord4
søgeord5
"søgesætning 2 der søges på" AND søgeord6
søgeord7
Avatar billede gbjensen65 Nybegynder
30. januar 2010 - 21:06 #14
Fint at du fandt en løsning.

Du skal bare tænke på at hvis du en dag skal søge rigtig meget data igennem, så er det nok ikke den bedste løsning, for det kræver at du udlæser hele din database / tabel, for så at søge alle poster igennem med dit script. Det kunne du have gjort direkte i databasen med en freetext søgning, og så kun hente de poster fra databasen der gav et hit.

Mvh. Lars
Avatar billede Mik2000 Professor
05. februar 2010 - 16:25 #15
Yep det er rigtigt, men det er ikke så meget data her

CCodam - læg et svar og der er point, og gbjensen65 læg også et, så får du også nogle af dem

Tak for svarene
Avatar billede Mik2000 Professor
15. februar 2010 - 22:00 #16
Hej, da der er gået 10 dages tid må jeg hellere lukke denne. Da ingen af jer har lagt et svar lukkes den hermed blog
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester