simenss Skrevet 17. oktober 2007 Del Skrevet 17. oktober 2007 (endret) Jeg har en database med blant annet en rad for produktnavn og en rad for varenummer. Kunden skal med søkemotoren kunne søke gjennom disse to radene. Si at brukeren søker etter "lg lcd tv". Da ønsker jeg at spørringen skal returnere alle produkter som inneholder disse tre ordene. Ordene kan enten stå for seg selv, eller som en del av et annet ord. Produkter som inneholder "FLAT-TV" skal returneres på søk etter "tv" osv. Man kan selvfølgelig splitte søkestrengen i en array, legge til REGEXP for hvert ord osv. men hadde håpet (og regner med) at det finnes en litt mer elegant og effektiv løsning. EDIT: Systemet inneholder ca. 7000 produkter, og kjører med mySQL. Endret 17. oktober 2007 av simenss Lenke til kommentar
Manfred Skrevet 17. oktober 2007 Del Skrevet 17. oktober 2007 hvis du ikke har så mange varer kan du gjøre det slik: SELECT * FROM products WHERE name LIKE '%tv%' Ellers er det mange måter å gjøre fulltekstsøk på, men i og med at jeg aldri har hatt særlig behov for det, så kan jeg dessverre lite om det. Lenke til kommentar
kaffenils Skrevet 17. oktober 2007 Del Skrevet 17. oktober 2007 Du sier jo ikke noe om hvilket databasesysem du bruker. De fleste databaser har en eller anne funksjon for fulltekst indexering og søking, enten innebygget eller som et 3djepartsverktøy. Disse er som skapt for denne jobben. Lenke til kommentar
simenss Skrevet 17. oktober 2007 Forfatter Del Skrevet 17. oktober 2007 Du sier jo ikke noe om hvilket databasesysem du bruker. De fleste databaser har en eller anne funksjon for fulltekst indexering og søking, enten innebygget eller som et 3djepartsverktøy. Disse er som skapt for denne jobben. Systemet inneholder ca. 7000 produkter, og kjører med mySQL. Vesentlig informasjon jeg burde inkludert fra starten av. Lenke til kommentar
kaffenils Skrevet 17. oktober 2007 Del Skrevet 17. oktober 2007 Vet at MySQL har støtte for fulltekstindexering, men jeg har aldri brukt det. Lenke til kommentar
phpp Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 Heisann. Det jeg gjør for å søke etter ALLE ordene er enkelt og greit: /* søkeord */ $search = "lg tv lcd"; /* splitte opp søkeord */ $search = explode(" ", $search); /* søkefelt i databasen: */ $searchFields = "productTitle,productDescription,productKeywords"; /* mysql spørring: */ $sql = "SELECT productTitle FROM products WHERE "; foreach($search as $kw) { $sql .= "CONCAT($searchFields) LIKE '%$kw%' OR "; } $sql = substr($sql,0,strlen($sql)-3); /* kjør spørringen */ Forklaringen av dette er enkelt og greit: "CONCAT" i mysql slår sammen ting. F.eks "CONCAT("HEY","THERE")" vil da gi "HEYTHERE". Så nå slår jeg sammen innholdet i alle feltene du skal la brukeren søke i som er $searchFields. Det andre jeg gjør er å splitte søkeordet og gå igjennom alle søkeordene og legge de inn etter WHERE med "OR" imellom. Det som skjer da er at den søker på hvert eneste ord. Om du skal ha full match med alle ord må du søke med "AND" i mellom .. Beklager dårlig formulert. Er trøtt Om dette hjalp vennligst endre tittel i førstepost til "[LØST] <tittel>" og skriv forklaring på hvordan du gjorde det. Dette kan hjelpe andre med samme problem. Om en post hjalp deg vennligst referer til den. Lenke til kommentar
Manfred Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 (endret) Det er ganske stygt å bruke LIKE OR LIKE OR.... Det er ekstremt lite optimalt i så fall... Fulltekstindeksering / fulltekstsøk er veien å gå, men i mysql har jeg ingen kunnskap her. Endret 18. oktober 2007 av Manfred Lenke til kommentar
roac Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 Det er ganske stygt å bruke LIKE OR LIKE OR.... Det er ekstremt lite optimalt i så fall... Fulltekstindeksering / fulltekstsøk er veien å gå, men i mysql har jeg ingen kunnskap her. Istemmes. I det hele tatt er like '%noe' grisestygt, for det forhindrer en hver bruk av indekser, og man får garantert table scan. Fulltekstsøk er tingen. Lenke til kommentar
simenss Skrevet 18. oktober 2007 Forfatter Del Skrevet 18. oktober 2007 Fulltekstsøk er tingen. Men hvordan? Lenke til kommentar
kaffenils Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 Istemmes. I det hele tatt er like '%noe' grisestygt, for det forhindrer en hver bruk av indekser, og man får garantert table scan. *pirke* table- eller indexscan *pirke*. Selv om det ikke gjør saken særlig mye bedre. Men hvordan? Hva med å prøve å lese MySQL-dokumentasjonen. Lenke til kommentar
Invert Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 (endret) http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html Google er din venn! Finnes ikke alt for mye optimaliserings guider om dette på nett. Men har selv brukt FULLTEXT søk og det er enorm forskjell fra LIKE, vi snakker 30 sek/minutter med LIKE ned til sekunder med FULLTEXT. Da på store tabeller. (700000+ rows) Har du phpMyAdmin? Om du går inn der og oppretter noen fulltext indekser på de feltene du er ute etter har du noe å søke i. Eller på manuell måte. mysql en søkevariabel: select * from tablename where match (produkt,beskrivelse,produktnavn) against('+$sokeord' IN BOOLEAN MODE) order by produktnavn ASC Disse feltene må inkluderes i fulltext indeksen i eksempelet over: produkt,beskrivelse,produktnavn mysql to søkevariabler: select * from tablename where match (produkt,beskrivelse,produktnavn) against('+$sokeord +$sokeord2' IN BOOLEAN MODE) order by produktnavn ASC Kombiner dette med LIKE setningen lenger oppe, så du kan søke etter flere ord om søkevariablen er "bilstereo sony". Bare spør mer. Har litt dårlig tid nå, men har litt erfaring Lykke til! Endret 18. oktober 2007 av Invert Lenke til kommentar
simenss Skrevet 18. oktober 2007 Forfatter Del Skrevet 18. oktober 2007 Bare spør mer. Har litt dårlig tid nå, men har litt erfaring Lykke til! Takk Manualen er fin den, men når det kommer til emner hvor jeg ikke kan noe fra før, er det fint med litt ekstra drahjelp. Endte opp med følgende spørring når jeg kombinerte spørringen med phpps kode: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg' IN BOOLEAN MODE) OR MATCH (product_id,product_name,product_manufacturers_id) against('+tv' IN BOOLEAN MODE) Det var kanskje ikke dette du mente med "Kombiner dette med LIKE setningen lenger oppe"? Lenke til kommentar
Invert Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 (endret) Bare spør mer. Har litt dårlig tid nå, men har litt erfaring Lykke til! Takk Manualen er fin den, men når det kommer til emner hvor jeg ikke kan noe fra før, er det fint med litt ekstra drahjelp. Endte opp med følgende spørring når jeg kombinerte spørringen med phpps kode: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg' IN BOOLEAN MODE) OR MATCH (product_id,product_name,product_manufacturers_id) against('+tv' IN BOOLEAN MODE) Det var kanskje ikke dette du mente med "Kombiner dette med LIKE setningen lenger oppe"? Tenkte mer på dette: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg +tv' IN BOOLEAN MODE) Da får du alt med lg og tv i seg. Dersom du skal ha OR skulle det holde med å ta bort + ene slik at det blir: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('lg tv' IN BOOLEAN MODE) SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('lg tv' IN BOOLEAN MODE) Eller på denne måten blir det jo litt kjapt skrevet: $search = "lg tv lcd"; $search = explode(" ", $search); $sql = "SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against(' "; foreach($search as $kw) { $sql .= "$kw"; } $sql .= "' IN BOOLEAN MODE"); Noe sånt eventuelt sette en + forran $kw. Endret 18. oktober 2007 av Invert Lenke til kommentar
roac Skrevet 18. oktober 2007 Del Skrevet 18. oktober 2007 *pirke* table- eller indexscan *pirke*. Selv om det ikke gjør saken særlig mye bedre. Så sant, så sant Lenke til kommentar
simenss Skrevet 20. oktober 2007 Forfatter Del Skrevet 20. oktober 2007 Tenkte mer på dette: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg +tv' IN BOOLEAN MODE) Jeg har et produkt hvor product_name er lik LG 19 LCD L1918S-SN TCO-03 Silver 1280x1024, 5ms, 700:1 -Demo. Kjørte følgende spørring: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg +lcd' IN BOOLEAN MODE) Men uten resultat. Prøvde også med kun 'lg' men får heller ikke da noe resultat. Har selvfølgelig prøvd med både store og små bokstaver. Har jeg missforstått noe? Lenke til kommentar
Invert Skrevet 20. oktober 2007 Del Skrevet 20. oktober 2007 Tenkte mer på dette: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg +tv' IN BOOLEAN MODE) Jeg har et produkt hvor product_name er lik LG 19 LCD L1918S-SN TCO-03 Silver 1280x1024, 5ms, 700:1 -Demo. Kjørte følgende spørring: SELECT product_name FROM products WHERE MATCH (product_id,product_name,product_manufacturers_id) against('+lg +lcd' IN BOOLEAN MODE) Men uten resultat. Prøvde også med kun 'lg' men får heller ikke da noe resultat. Har selvfølgelig prøvd med både store og små bokstaver. Har jeg missforstått noe? Hei igjen... Du har sikkert ikke fått endret på konfigurasjonen til MySQL'en din. Den er standard på at den bare indekserer ord med 4 bokstaver/tall i seg. Derfor må du inn i konfigurasjonen og få endret det til 3 eller 2 ettersom hva du ønsker. Endre dette i konfigurasjonen: ft_min_word_len=3 eller til ft_min_word_len=2. Tallet spesifiserer altså antallet bokstaver i et ord. Så må du starte mysql deamonen din på nytt, og rebuilde indexene dine så er alt klart! Lenke til kommentar
simenss Skrevet 26. oktober 2007 Forfatter Del Skrevet 26. oktober 2007 Hei igjen... Du har sikkert ikke fått endret på konfigurasjonen til MySQL'en din. Den er standard på at den bare indekserer ord med 4 bokstaver/tall i seg. Derfor må du inn i konfigurasjonen og få endret det til 3 eller 2 ettersom hva du ønsker. Endre dette i konfigurasjonen: ft_min_word_len=3 eller til ft_min_word_len=2. Tallet spesifiserer altså antallet bokstaver i et ord. Så må du starte mysql deamonen din på nytt, og rebuilde indexene dine så er alt klart! Personen jeg lager søkefunksjonen for leier et webhotell hos subsys.no. Det er derfor begrenset med konfigurasjonsmuligheter. Er det mulig å definere disse variablene i PHP-scriptet eller liknende? Lenke til kommentar
Invert Skrevet 29. oktober 2007 Del Skrevet 29. oktober 2007 Hei igjen... Du har sikkert ikke fått endret på konfigurasjonen til MySQL'en din. Den er standard på at den bare indekserer ord med 4 bokstaver/tall i seg. Derfor må du inn i konfigurasjonen og få endret det til 3 eller 2 ettersom hva du ønsker. Endre dette i konfigurasjonen: ft_min_word_len=3 eller til ft_min_word_len=2. Tallet spesifiserer altså antallet bokstaver i et ord. Så må du starte mysql deamonen din på nytt, og rebuilde indexene dine så er alt klart! Personen jeg lager søkefunksjonen for leier et webhotell hos subsys.no. Det er derfor begrenset med konfigurasjonsmuligheter. Er det mulig å definere disse variablene i PHP-scriptet eller liknende? Dette må gjøres i mysql config, og mysql må restartes. Dette kan ikke kjøres live. Dessverre. Lenke til kommentar
roac Skrevet 29. oktober 2007 Del Skrevet 29. oktober 2007 Dette må gjøres i mysql config, og mysql må restartes. Dette kan ikke kjøres live. Dessverre. Og hvis jeg ikke har forstått det helt feil, så har dette potensielt en ganske så betydelig negativ impact på ytelse på serveren, og derfor er det vel relativt lite sannsynlig at en ISP kommer til å gjøre noe med dette. Lenke til kommentar
simenss Skrevet 30. oktober 2007 Forfatter Del Skrevet 30. oktober 2007 Finnes det noen andre metoder for å kunne søke gjennom ord fra 2 tegn? Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå