[MySQL] Fulltext search met een streepje (-)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Ik maak in mijn systeem gebruik van fulltext search in MySQL. Dat werkt overal prima, behalve op het kenteken veld. Dit komt doordat daar een streepje (-) instaat.

Ik heb geprobeerd met of zonder BOOLEAN MODE, gebruik van de REPLACE tag om het streepje te verwijderen (wat niet lukte) en heel internet afgezocht, maar helaas geen oplossing gevonden.

Ook heb ik het minimale aantal karakters als op 3 gezet (ft_min_word_len=3) zodat kentekens als 11-AAA-2 gevonden kunnen worden, maar dan blijf ik zitten met kentekens zoals 11-AA-BB. Het minimale aantal karakters op 2 zetten heeft helemaal geen zin, want dan krijg ik teveel ruis in mijn zoekresultaten.

Ik wil geen gebruikmaken van extra software zoals Sphinx, maar zoek een "simpele" oplossing.

MySQL:
1
SELECT id FROM auto WHERE MATCH (kenteken) AGAINST('".mysql_real_escape_string($zoekwoord)."' IN BOOLEAN MODE)


Mijn idee was om de streepjes weg te halen middels PHP
PHP:
1
$zoekwoord = str_replace('-','',$_POST['zoekwoord']);

En dan via REPLACE in MySQL ook het streepje te verwijderen.
MySQL:
1
SELECT id FROM auto WHERE MATCH (REPLACE(kenteken, '-', '')) AGAINST('".mysql_real_escape_string($zoekwoord)."' IN BOOLEAN MODE)

Maar dat lukt niet.

Wie kan mij een beetje op weg helpen?

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Je laatste poging werkt niet omdat je dan niet meer met de letterlijke fulltext index werkt. Je zou dan de data moeten opslaan zonder - en + karakters, desnoods/wellicht in een losse kolom voor het zoeken.

{signature}


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Ik heb inmiddels min of meer een oplossing gevonden, al is dit niet de gewenste!

Quote van: http://mysqlonlinehelp.wo...ndex-for-myisam-in-mysql/
If you want to change the set of characters that are considered word characters, you can do so in two ways. Suppose that you want to treat the hyphen character (‘-’) as a word character. Use either of these methods:

o Modify the MySQL source: In myisam/ftdefs.h, see the true_word_char() and misc_word_char() macros. Add '-' to one of those macros and recompile MySQL.

o Modify a character set file: This requires no recompilation. The true_word_char() macro uses a “character type” table to distinguish letters and numbers from other characters. . You can edit the <ctype><map> contents in one of the character set XML files to specify that '-' is a “letter.” Then use the given character set for your FULLTEXT indexes.

After making the modification, you must rebuild the indexes for each table that contains any FULLTEXT indexes.

Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Is een LIKE of RLIKE niet voldoende in dit geval?
Voer je altijd het volledige kenteken in of (soms) een deel?

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Ik heb inmiddels een oplossing gevonden :). Voor de liefhebber:

- Zet allereerst de minimale aantal karakters op 2 (ft_min_word_len=2).
- Maak de fulltext index opnieuw aan.
- Maak gebruik van de BOOLEAN MODE:

MySQL:
1
SELECT id FROM auto WHERE MATCH (kenteken) AGAINST('".mysql_real_escape_string($zoekwoord)."' IN BOOLEAN MODE)


- Zet quotes ( " ) om het zoekwoord:

PHP:
1
$zoekwoord = "\"".$_POST['zoekwoord']."\"";

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Het lijkt me trouwens dat je dit beter op een andere manier dan met fulltext search van MySQL op zou kunnen lossen. Fulltext search is beter geoptimaliseerd voor lappen tekst. Voor een dergelijk kort veld met een zo strikt formaat kun je veel betere oplossingen verzinnen. Je weet dat de nummerborden met 3 letters ook 1 cijfer hebben en dat jij daar nu nog steeds niet op kunt zoeken?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Janoz schreef op donderdag 28 april 2011 @ 16:53:
Het lijkt me trouwens dat je dit beter op een andere manier dan met fulltext search van MySQL op zou kunnen lossen. Fulltext search is beter geoptimaliseerd voor lappen tekst. Voor een dergelijk kort veld met een zo strikt formaat kun je veel betere oplossingen verzinnen. Je weet dat de nummerborden met 3 letters ook 1 cijfer hebben en dat jij daar nu nog steeds niet op kunt zoeken?
Nummerborden met 3 letters en 1 cijfer kunnen gewoon gevonden worden. Werkt prima nu.
Als je betere oplossingen hebt dan hoor ik het graag. Performance is niet belangrijk aangezien er misschien 1x per half uur een zoekopdracht gedaan wordt

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Waarom zou LIKE niet voldoen?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik zou voor zoiets gaan:

code:
1
2
3
4
5
id   kenteken   kenteken_formatted
==   ========   ==================
1    12ab34     12-ab-34
2    7cd281     7-cd-281
3    281s1s     281-s-11


Bij 't opslaan sla je de input (evt. ontdaan van whitespace) van de gebruiker op in kenteken_formatted dus zoals hij/zij het heeft ingevoerd. En je zorgt dat je alles behalve a-z en 0-9 uit kenteken_formatted sloopt en opslaat in kenteken.

Je krijgt dan:
code:
1
2
3
4
5
function normalizelicenceplate($value) {
  return replace(tolower($value), '[^a-z0-9]', '');
}

db.insert("insert into mytable (kenteken, kenteken_formatted) values ('$normalizelicenceplate($input)', '$input')");

Bij het zoeken gebruik je eveneens:
code:
1
$result = db.select("select * from mytable where kenteken = '$normalizelicenceplate($input)'");
SQL injection en al de zaken achterwege gelaten; het is pseudo code: ter illustratie
Dan heb je een eenduidige manier van zaken opslaan, hou je toch de representatie zoals die bedoeld is/was en kun je veel beter zoeken doordat je meuk als streepjes, haakjes, whitespace en weet-ik-veel lekker kunt negeren. Ongeacht hoe ik een kenteken invoer in het zoekveld wordt 'ie dan (mits bekend uiteraard) toch gevonden. Indexje op kenteken (en dus niet kenteken_formatted; die wordt enkel gebruikt voor presentatiedoeleinden) en gaan. Een FTS hiervoor gebruiken is simpelweg overkill en daarbij is FTS helemaal niet bedoeld voor dit soort zaken.

[ Voor 25% gewijzigd door RobIII op 28-04-2011 17:23 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1