MYSQL LIKE,CONTAINS vraagje
Beste forumleden,
Ik wil graag kunnen zoeken op de bedrijfsnaam op basis wat de eindgebruiker invoert.
IK heb een bedrijf genaamd Emtek Ergonomics.
Als ik zoek op Emtek vind die dit bedrijf wel maar als ik zoek op bijv: emtek-test of koekie-emtek vind die helemaal niets.
Welke functie zoekt gewoon op alles zodat die altijd kijkt of akarakters voorkomen in de hele string in de klom?
Toevoeging op 18/10/2017 13:31:40:
Hier vind ook niets op:
SELECT * FROM bedrijven WHERE LOCATE('emtek-ergonomics---bureaustoel-op-maat',bedrijfsnaam)
Maar dit vind die wel:
SELECT * FROM bedrijven WHERE LOCATE('emtek',bedrijfsnaam)
Ik wil graag kunnen zoeken op de bedrijfsnaam op basis wat de eindgebruiker invoert.
IK heb een bedrijf genaamd Emtek Ergonomics.
Als ik zoek op Emtek vind die dit bedrijf wel maar als ik zoek op bijv: emtek-test of koekie-emtek vind die helemaal niets.
Welke functie zoekt gewoon op alles zodat die altijd kijkt of akarakters voorkomen in de hele string in de klom?
Toevoeging op 18/10/2017 13:31:40:
Hier vind ook niets op:
SELECT * FROM bedrijven WHERE LOCATE('emtek-ergonomics---bureaustoel-op-maat',bedrijfsnaam)
Maar dit vind die wel:
SELECT * FROM bedrijven WHERE LOCATE('emtek',bedrijfsnaam)
Quote:
Welke functie zoekt gewoon op alles zodat die altijd kijkt of akarakters voorkomen in de hele string in de klom?
De functie die je zelf schrijft ;-)
Hak je hele zoek-string in stukken ("woorden"), bijvoorbeeld met preg_split('/\\W+/',$search)
Vervolgens zoek je alle bedrijven die op tenminste van een van deze woorden een LIKE match heeft. Degene met de meeste matches (woorden) toon je bovenaan.
De eerste LOCATE() levert waarschijnlijk niets op omdat LOCATE() exacte matches uitvoert, en blijkbaar niets (exact) kon matchen.
Wat je zou kunnen doen:
- volg de suggestie van @Rob op
- gebruik fulltext searches, dit houdt wel in dat je goed nadenkt over hoe je indexeert en hoe je dit opzet
- maak gebruik van externe oplossingen om text te indexeren
- verander de manier waarop je zoekt, introduceer bijvoorbeeld keywords/tags, en laat je zoekfunctionaliteit hier mee werken, of maak gebruik van een soort van Faceted Search waarbij je een collectie data steeds specifieker filtert
Wat je zou kunnen doen:
- volg de suggestie van @Rob op
- gebruik fulltext searches, dit houdt wel in dat je goed nadenkt over hoe je indexeert en hoe je dit opzet
- maak gebruik van externe oplossingen om text te indexeren
- verander de manier waarop je zoekt, introduceer bijvoorbeeld keywords/tags, en laat je zoekfunctionaliteit hier mee werken, of maak gebruik van een soort van Faceted Search waarbij je een collectie data steeds specifieker filtert
Rob Doemaarwat op 18/10/2017 14:09:07:
De functie die je zelf schrijft ;-)
Hak je hele zoek-string in stukken ("woorden"), bijvoorbeeld met preg_split('/\\W+/',$search)
Vervolgens zoek je alle bedrijven die op tenminste van een van deze woorden een LIKE match heeft. Degene met de meeste matches (woorden) toon je bovenaan.
Quote:
Welke functie zoekt gewoon op alles zodat die altijd kijkt of akarakters voorkomen in de hele string in de klom?
De functie die je zelf schrijft ;-)
Hak je hele zoek-string in stukken ("woorden"), bijvoorbeeld met preg_split('/\\W+/',$search)
Vervolgens zoek je alle bedrijven die op tenminste van een van deze woorden een LIKE match heeft. Degene met de meeste matches (woorden) toon je bovenaan.
Kan je hier een voorbeeld voor geven in code?
$input = "emtek-ergonomics---bureaustoel-op-maat"
Als iemand zoekt op iets wat spaties heb vervang ik deze al door "-" dus hier kan ik de woorden op splitten vermoed ik.
Hoe gaat dit er dan in de sql query uitzien?
Stel ik zoek op twee woorden: "foo" en "bar" (voorheen "foo---bar")
(je sorteert dus eigenlijk op de bedrijfsnaam met de laagste score = meeste matches)
Code (php)
1
2
3
2
3
select * from bedrijven
where bedrijfsnaam like "%foo%" or bedrijfsnaam like "%bar%"
order by if(bedrijfsnaam like "%foo%",0,1) + if(bedrijfsnaam like "%bar%",0,1)
where bedrijfsnaam like "%foo%" or bedrijfsnaam like "%bar%"
order by if(bedrijfsnaam like "%foo%",0,1) + if(bedrijfsnaam like "%bar%",0,1)
(je sorteert dus eigenlijk op de bedrijfsnaam met de laagste score = meeste matches)
Top bedankt voor de reacties, nog 1 vraagje:
Hoe hak ik mijn string netjes in stukken en kan ik deze eenvoudig in sql vergelijken.
Stel ik heb een lange string van: woord1-woord2-woord3-woord4 etc...
Ik kan natuurlijk niet in mijn mysql query 10x OR like zetten?
str_replace("-"," ",$string) geeft mij alle woorden los van elkaar maar hoe dan verder?
Hoe hak ik mijn string netjes in stukken en kan ik deze eenvoudig in sql vergelijken.
Stel ik heb een lange string van: woord1-woord2-woord3-woord4 etc...
Ik kan natuurlijk niet in mijn mysql query 10x OR like zetten?
str_replace("-"," ",$string) geeft mij alle woorden los van elkaar maar hoe dan verder?
Je kunt daar prima 10x OR like zetten. Nog wel meer ook. Je moet het alleen op basis van je (aantal) woorden doen. Dus als je 5 woorden hebt, plak voeg je 5x een like aan je WHERE toe, en 5x een if() aan je ORDER BY. Vervolgens plak je de hele boel samen ala bovenstaande SQL en uitvoeren maar.
Toevoeging op 18/10/2017 18:12:19:
Ter info: die preg_split('/\\W+/',$string) splitst de $string op karakters die *niet* "in een woord" zitten (let op: hoofdletter W). Met karakters die "in een woord" zitten bedoelt een regex a-z, A-Z, 0-9, en "_" (http://www.regular-expressions.info/shorthand.html). De $string zal dus in een array gebroken worden op alle tekens (1 of meer) die daar niet in zitten. Met $string = "bla-bla bla----bla * * bla" levert dit dus een array op met 5x "bla".
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
$where = $order = [];
foreach(preg_split('/\\W+/',$string) as $word){
$where[] = ...
$order[] = ...
}
$sql = '
select * from ...
where ' . implode(' or ',$where) . '
order by ' . implode('+',$order);
foreach(preg_split('/\\W+/',$string) as $word){
$where[] = ...
$order[] = ...
}
$sql = '
select * from ...
where ' . implode(' or ',$where) . '
order by ' . implode('+',$order);
Toevoeging op 18/10/2017 18:12:19:
Ter info: die preg_split('/\\W+/',$string) splitst de $string op karakters die *niet* "in een woord" zitten (let op: hoofdletter W). Met karakters die "in een woord" zitten bedoelt een regex a-z, A-Z, 0-9, en "_" (http://www.regular-expressions.info/shorthand.html). De $string zal dus in een array gebroken worden op alle tekens (1 of meer) die daar niet in zitten. Met $string = "bla-bla bla----bla * * bla" levert dit dus een array op met 5x "bla".
Gewijzigd op 18/10/2017 18:15:10 door Rob Doemaarwat
Beste Rob,
Bedankt voor de code, ik heb hem even getest maar denk dat ik wat fout doe:
Resultaat: select * from bedrijven where emtek or ergonomics or bureaustoel or op or maat order by emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maatUnknown column 'emtek' in 'where clause'
Bedankt voor de code, ik heb hem even getest maar denk dat ik wat fout doe:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</php
$where = $order = [];
foreach(preg_split('/\\W+/',$input) as $word)
{
$where[] = $word;
$order[] = $input;
}
$q = '
select * from bedrijven
where ' . implode(' or ',$where) . '
order by ' . implode('+',$order);
echo $q;
?>
$where = $order = [];
foreach(preg_split('/\\W+/',$input) as $word)
{
$where[] = $word;
$order[] = $input;
}
$q = '
select * from bedrijven
where ' . implode(' or ',$where) . '
order by ' . implode('+',$order);
echo $q;
?>
Resultaat: select * from bedrijven where emtek or ergonomics or bureaustoel or op or maat order by emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maat+emtek-ergonomics---bureaustoel-op-maatUnknown column 'emtek' in 'where clause'
Is het bovenstaande niet precies wat fulltext searches doen, maar dan geïndexeerd? :p
Hi Thomas,
Moet je als je full text search wilt gebruiken elke keer de tabel updaten of kan je eenmalig zeggen: ALTER TABLE bedrijven
ADD FULLTEXT(bedrijfsnaam)
Moet je als je full text search wilt gebruiken elke keer de tabel updaten of kan je eenmalig zeggen: ALTER TABLE bedrijven
ADD FULLTEXT(bedrijfsnaam)
Nadeel van fulltext is dat je alleen op hele woorden zoekt, of in ieder geval vanaf het begin ("bar*" vindt niet "foobar"). Met een LIKE zoek je gewoon in het hele woord (begin/midden/eind: "%bar%" vindt "foobar" wel). Evt. kun je daar met je ORDER BY "score" rekening mee houden door te doen (= 10 punten bij een full-word match, 1 punt voor een "in woord" match).
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
if(
bedrijfsnaam LIKE "% foo %" OR
bedrijfsnaam LIKE "foo %" OR
bedrijfsnaam LIKE "% foo",
10,
if(bedrijfsnaam LIKE "%foo%",1,0)
)
bedrijfsnaam LIKE "% foo %" OR
bedrijfsnaam LIKE "foo %" OR
bedrijfsnaam LIKE "% foo",
10,
if(bedrijfsnaam LIKE "%foo%",1,0)
)
Gewijzigd op 19/10/2017 21:50:23 door Rob Doemaarwat




