Tutorials
Fulltext indexes in MySQL
Uitleg en voorbeelden over het gebruiken van fulltext indexes in MySQL waarmee je sneller door een database kan zoeken.
Pagina 1
Fulltext indexes met mysql
Ik las gister een artikel over MySQL indexes op www.databasejournal.com. Ik was echt verwonderd dat het zo simpel was. Omdat Sander Draaier recent een berichtje plaatste op het forum met de vraag hoe MySQL indexes werkt, schrijf ik er een artikel over.
Ik ga er vanuit dat je een al wat geavanceerdere MySQL gebruiker bent en weet dat je PHMyAdmin of een ander database management programma moet gebruiken om de SQL codes uit te voeren.
De functies in MySQL MATCH() kan in versies vanaf 3.23.23 gebruikt worden. De wat geavanceerdere variant IN BOOLEAN MODE is beschikbaar vanaf versie 4. Ik leer je in deze tutorial hoe je FULLTEXT kan zoeken in een MySQL database. Dit is alleen mogelijk in de MyISAM tabellen. Dit is de standaard MySQL tabel. Heb je dus iets anders ingesteld, dan kun je TYPE=MyISAM; achter je tabel creëer code zetten (voorbeeld zometeen).
MySQL FULLTEXT indexes is makkelijk en vooral geen overbodige luxe om te gebruiken omdat het erg snel is. Als je bijvoorbeeld een tabel in je database hebt met 50 rijen en er 10 keer per minuut iets wordt aangevraagd dan is dit al handig om te gebruiken. Al helemaal dus als je een tabel in je database hebt met 50.000 rijen (zoals het forum op PHPhulp) en die 100+ keer per minuut benaderd wordt. Om deze tutorial te begrijpen en om er zoveel mogelijk van te leren kun je de volgende tabel aanmaken:
<?
CREATE TABLE fulltext_test (
msg VARCHAR(150),
FULLTEXT(msg)
) TYPE=MyISAM;
?>
Je ziet nu waarschijnlijk een nieuwe optie, FULLTEXT(msg);. Om zo meteen gebruik te kunnen maken van FULLTEXT indexes moet de kolomnaam waarop je wilt zoeken geïndexeerd zijn. Dit doe je dus met de functie FULLTEXT(). In de functie moet de naam van de kolom worden opgegeven. In dit geval is dit de naam: ‘msg’.
Zet de volgende waardes in deze tabel:
<?
INSERT INTO fulltext_test VALUES
('4 uur phphulp, dat zouden meer mensen moeten doen'),
('altijd weer die phphulp, het zou verboden moeten worden'),
('phphulp, zoals php ooit bedoelt was'),
('handig, van phphulp.'),
('elke klus, een phphulp klus'),
('PHPhulp, geen fratsen, dat scheelt..'),
('PHPhulp, daar plukt ú de vruchten van...'),
('phphulp, bent u binnenkort ook een ex-man en heeft u een extra-werkgever nodig?');
?>
Ik raad je aan om deze test tabel aan te maken met deze test waardes zodat je het helemaal zult begrijpen. Als je al een tabel hebt en je wilt het toch daarop toepassen dan kun je de volgende SQL code gebruiken (via ALTER).
<?
ALTER TABLE fulltext_test ADD FULLTEXT(msg);
?>
De naam ‘msg’ moet je dan vervangen met de naam van jou kolom waarop je FULLTEXT indexes wilt toepassen.
Ik ga er vanuit dat je een al wat geavanceerdere MySQL gebruiker bent en weet dat je PHMyAdmin of een ander database management programma moet gebruiken om de SQL codes uit te voeren.
De functies in MySQL MATCH() kan in versies vanaf 3.23.23 gebruikt worden. De wat geavanceerdere variant IN BOOLEAN MODE is beschikbaar vanaf versie 4. Ik leer je in deze tutorial hoe je FULLTEXT kan zoeken in een MySQL database. Dit is alleen mogelijk in de MyISAM tabellen. Dit is de standaard MySQL tabel. Heb je dus iets anders ingesteld, dan kun je TYPE=MyISAM; achter je tabel creëer code zetten (voorbeeld zometeen).
MySQL FULLTEXT indexes is makkelijk en vooral geen overbodige luxe om te gebruiken omdat het erg snel is. Als je bijvoorbeeld een tabel in je database hebt met 50 rijen en er 10 keer per minuut iets wordt aangevraagd dan is dit al handig om te gebruiken. Al helemaal dus als je een tabel in je database hebt met 50.000 rijen (zoals het forum op PHPhulp) en die 100+ keer per minuut benaderd wordt. Om deze tutorial te begrijpen en om er zoveel mogelijk van te leren kun je de volgende tabel aanmaken:
<?
CREATE TABLE fulltext_test (
msg VARCHAR(150),
FULLTEXT(msg)
) TYPE=MyISAM;
?>
Je ziet nu waarschijnlijk een nieuwe optie, FULLTEXT(msg);. Om zo meteen gebruik te kunnen maken van FULLTEXT indexes moet de kolomnaam waarop je wilt zoeken geïndexeerd zijn. Dit doe je dus met de functie FULLTEXT(). In de functie moet de naam van de kolom worden opgegeven. In dit geval is dit de naam: ‘msg’.
Zet de volgende waardes in deze tabel:
<?
INSERT INTO fulltext_test VALUES
('4 uur phphulp, dat zouden meer mensen moeten doen'),
('altijd weer die phphulp, het zou verboden moeten worden'),
('phphulp, zoals php ooit bedoelt was'),
('handig, van phphulp.'),
('elke klus, een phphulp klus'),
('PHPhulp, geen fratsen, dat scheelt..'),
('PHPhulp, daar plukt ú de vruchten van...'),
('phphulp, bent u binnenkort ook een ex-man en heeft u een extra-werkgever nodig?');
?>
Ik raad je aan om deze test tabel aan te maken met deze test waardes zodat je het helemaal zult begrijpen. Als je al een tabel hebt en je wilt het toch daarop toepassen dan kun je de volgende SQL code gebruiken (via ALTER).
<?
ALTER TABLE fulltext_test ADD FULLTEXT(msg);
?>
De naam ‘msg’ moet je dan vervangen met de naam van jou kolom waarop je FULLTEXT indexes wilt toepassen.
Pagina 2
Zoeken in een tabel
Als je iets zou zoeken in de database, zou je dit normaal doen met deze query: (je wilt een zin met het woord ooit erin).
<?
mysql> SELECT msg FROM fulltext_test WHERE msg LIKE '%ooit%';
+-------------------------------------+
| msg |
+-------------------------------------+
| phphulp, zoals php ooit bedoelt was |
+-------------------------------------+
1 row in set (0.00 sec)
?>
Omdat het veld msg nu geïndexeerd is (immers met de MySQL functie FULLTEXT()) kun je het volgende doen. Je doet eigenlijk het volgende: “Je MATCHed een geïndexeerde kolom AGAINST een waarde”.
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('ooit');
+-------------------------------------+
| msg |
+-------------------------------------+
| phphulp, zoals php ooit bedoelt was |
+-------------------------------------+
1 row in set (0.00 sec)
?>
MySQL zal geen resultaat geven bij woorden minder dan of gelijk aan 3 karakters met het zoekwoord. Daarom zou dit geen resultaat geven:
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('ooi');
Empty set (0.00 sec)
?>
Er zal ook geen resultaat getoond worden als het zoekwoord in meer dan 50% van de tabel gevonden word. Dit zal daarom geen resultaat geven (phphulp staat in elke regel, meer dan 50% dus):
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('phphulp');
Empty set (0.00 sec)
?>
Maar de volgende query dus wel (geeft slechts 2 resultaten met het woord).
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('moeten');
+---------------------------------------------------------+
| msg |
+---------------------------------------------------------+
| 4 uur phphulp, dat zouden meer mensen moeten doen |
| altijd weer die phphulp, het zou verboden moeten worden |
+---------------------------------------------------------+
2 rows in set (0.00 sec)
?>
Hyperante zoekwoorden worden beschouwd als twee woorden. We zoeken op ex-man. Dit wordt helaas beschouwd als een deels woord (dus een woord minder dan of gelijk aan 3 karakters). De volgende query geeft dus geen resultaat.
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('ex-man');
Empty set (0.00 sec)
?>
Maar extra-werknemer (het bestaat niet maar als voorbeeld) zal wel een resultaat geven.
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('extra-werknemer')
;
+-------------------------------------------------------------------------------
--+
| msg
|
+-------------------------------------------------------------------------------
--+
| phphulp, bent u binnenkort ook een ex man en heeft u een extra-werkgever nodig
? |
+-------------------------------------------------------------------------------
--+
1 row in set (0.00 sec)
?>
Je kunt ook op twee woorden tegelijk zoeken. Dit doe je door in de functie AGAINST() woorden te scheiden van een komma. Voorbeeld:
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('elke, bedoelt');
+-------------------------------------+
| msg |
+-------------------------------------+
| phphulp, zoals php ooit bedoelt was |
| elke klus, een phphulp klus |
+-------------------------------------+
2 rows in set (0.00 sec)
?>
<?
mysql> SELECT msg FROM fulltext_test WHERE msg LIKE '%ooit%';
+-------------------------------------+
| msg |
+-------------------------------------+
| phphulp, zoals php ooit bedoelt was |
+-------------------------------------+
1 row in set (0.00 sec)
?>
Omdat het veld msg nu geïndexeerd is (immers met de MySQL functie FULLTEXT()) kun je het volgende doen. Je doet eigenlijk het volgende: “Je MATCHed een geïndexeerde kolom AGAINST een waarde”.
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('ooit');
+-------------------------------------+
| msg |
+-------------------------------------+
| phphulp, zoals php ooit bedoelt was |
+-------------------------------------+
1 row in set (0.00 sec)
?>
MySQL zal geen resultaat geven bij woorden minder dan of gelijk aan 3 karakters met het zoekwoord. Daarom zou dit geen resultaat geven:
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('ooi');
Empty set (0.00 sec)
?>
Er zal ook geen resultaat getoond worden als het zoekwoord in meer dan 50% van de tabel gevonden word. Dit zal daarom geen resultaat geven (phphulp staat in elke regel, meer dan 50% dus):
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('phphulp');
Empty set (0.00 sec)
?>
Maar de volgende query dus wel (geeft slechts 2 resultaten met het woord).
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('moeten');
+---------------------------------------------------------+
| msg |
+---------------------------------------------------------+
| 4 uur phphulp, dat zouden meer mensen moeten doen |
| altijd weer die phphulp, het zou verboden moeten worden |
+---------------------------------------------------------+
2 rows in set (0.00 sec)
?>
Hyperante zoekwoorden worden beschouwd als twee woorden. We zoeken op ex-man. Dit wordt helaas beschouwd als een deels woord (dus een woord minder dan of gelijk aan 3 karakters). De volgende query geeft dus geen resultaat.
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('ex-man');
Empty set (0.00 sec)
?>
Maar extra-werknemer (het bestaat niet maar als voorbeeld) zal wel een resultaat geven.
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('extra-werknemer')
;
+-------------------------------------------------------------------------------
--+
| msg
|
+-------------------------------------------------------------------------------
--+
| phphulp, bent u binnenkort ook een ex man en heeft u een extra-werkgever nodig
? |
+-------------------------------------------------------------------------------
--+
1 row in set (0.00 sec)
?>
Je kunt ook op twee woorden tegelijk zoeken. Dit doe je door in de functie AGAINST() woorden te scheiden van een komma. Voorbeeld:
<?
mysql> SELECT msg FROM fulltext_test WHERE MATCH(msg) AGAINST('elke, bedoelt');
+-------------------------------------+
| msg |
+-------------------------------------+
| phphulp, zoals php ooit bedoelt was |
| elke klus, een phphulp klus |
+-------------------------------------+
2 rows in set (0.00 sec)
?>
Pagina 3
Samenvatting
Deze regels gelden dus bij een MySQL FULLTEXT search:
- toont geen deels zoekwoorden (zoekwoord moet 4 of meer dan 4 karakters bevatten)
- toont geen resultaat als de match met het een zoekwoord minder dan 3 of gelijk is aan 3 karakters
- toont geen resultaat als het zoekwoord in meer dan 50% van de rijen gevonden is
- toont geen resultaat als het zoekwoord is gevonden in de 'stop lijst'
- toont geen resultaat als het zoekwoord een hyperante is (zoals: ex-man omdat de woorden ex en man appart bekeken worden), maar extra-werknemer weer wel omdat extra meer dan 4 karakters is en werknemer ook.
- de resultaten zijn op relevantie, descending
De woorden in de stoplijst zitten ergens diep verborgen in MySQL. De stopwoorden kunnen verschillen per MySQL versie. Het is dus verstandig om de stopwoorden op te zoeken per MySQL versie. Hier zijn de stopwoorden:
"a", "a's", "able", "about", "above", "according", "accordingly", "across", "actually", "after", "afterwards", "again", "against", "ain't", "all", "allow", "allows", "almost", "alone", "along", "already", "also", "although", "always", "am", "among", "amongst", "an", "and", "another", "any", "anybody", "anyhow", "anyone", "anything", "anyway", "anyways", "anywhere", "apart", "appear", "appreciate", "appropriate", "are", "aren't", "around", "as", "aside", "ask", "asking", "associated", "at", "available", "away", "awfully", "b", "be", "became", "because", "become", "becomes", "becoming", "been", "before", "beforehand", "behind", "being", "believe", "below", "beside", "besides", "best", "better", "between", "beyond", "both", "brief", "but", "by", "c", "c'mon", "c's", "came", "can", "can't", "cannot", "cant", "cause", "causes", "certain", "certainly", "changes", "clearly", "co", "com", "come", "comes", "concerning", "consequently", "consider", "considering", "contain", "containing", "contains", "corresponding", "could", "couldn't", "course", "currently", "d", "definitely", "described", "despite", "did", "didn't", "different", "do", "does", "doesn't", "doing", "don't", "done", "down", "downwards", "during", "e", "each", "edu", "eg", "eight", "either", "else", "elsewhere", "enough", "entirely", "especially", "et", "etc", "even", "ever", "every", "everybody", "everyone", "everything", "everywhere", "ex", "exactly", "example", "except", "f", "far", "few", "fifth", "first", "five", "followed", "following", "follows", "for", "former", "formerly", "forth", "four", "from", "further", "furthermore", "g", "get", "gets", "getting", "given", "gives", "go", "goes", "going", "gone", "got", "gotten", "greetings", "h", "had", "hadn't", "happens", "hardly", "has", "hasn't", "have", "haven't", "having", "he", "he's", "hello", "help", "hence", "her", "here", "here's", "hereafter", "hereby", "herein", "hereupon", "hers", "herself", "hi", "him", "himself", "his", "hither", "hopefully", "how", "howbeit", "however", "i", "i'd", "i'll", "i'm", "i've", "ie", "if", "ignored", "immediate", "in", "inasmuch", "inc", "indeed", "indicate", "indicated", "indicates", "inner", "insofar", "instead", "into", "inward", "is", "isn't", "it", "it'd", "it'll", "it's", "its", "itself", "j", "just", "k", "keep", "keeps", "kept", "know", "knows", "known", "l", "last", "lately", "later", "latter", "latterly", "least", "less", "lest", "let", "let's", "like", "liked", "likely", "little", "look", "looking", "looks", "ltd", "m", "mainly", "many", "may", "maybe", "me", "mean", "meanwhile", "merely", "might", "more", "moreover", "most", "mostly", "much", "must", "my", "myself", "n", "name", "namely", "nd", "near", "nearly", "necessary", "need", "needs", "neither", "never", "nevertheless", "new", "next", "nine", "no", "nobody", "non", "none", "noone", "nor", "normally", "not", "nothing", "novel", "now", "nowhere", "o", "obviously", "of", "off", "often", "oh", "ok", "okay", "old", "on", "once", "one", "ones", "only", "onto", "or", "other", "others", "otherwise", "ought", "our", "ours", "ourselves", "out", "outside", "over", "overall", "own", "p", "particular", "particularly", "per", "perhaps", "placed", "please", "plus", "possible", "presumably", "probably", "provides", "q", "que", "quite", "qv", "r", "rather", "rd", "re", "really", "reasonably", "regarding", "regardless", "regards", "relatively", "respectively", "right", "s", "said", "same", "saw", "say", "saying", "says", "second", "secondly", "see", "seeing", "seem", "seemed", "seeming", "seems", "seen", "self", "selves", "sensible", "sent", "serious", "seriously", "seven", "several", "shall", "she", "should", "shouldn't", "since", "six", "so", "some", "somebody", "somehow", "someone", "something", "sometime", "sometimes", "somewhat", "somewhere", "soon", "sorry", "specified", "specify", "specifying", "still", "sub", "such", "sup", "sure", "t", "t's", "take", "taken", "tell", "tends", "th", "than", "thank", "thanks", "thanx", "that", "that's", "thats", "the", "their", "theirs", "them", "themselves", "then", "thence", "there", "there's", "thereafter", "thereby", "therefore", "therein", "theres", "thereupon", "these", "they", "they'd", "they'll", "they're", "they've", "think", "third", "this", "thorough", "thoroughly", "those", "though", "three", "through", "throughout", "thru", "thus", "to", "together", "too", "took", "toward", "towards", "tried", "tries", "truly", "try", "trying", "twice", "two", "u", "un", "under", "unfortunately", "unless", "unlikely", "until", "unto", "up", "upon", "us", "use", "used", "useful", "uses", "using", "usually", "v", "value", "various", "very", "via", "viz", "vs", "w", "want", "wants", "was", "wasn't", "way", "we", "we'd", "we'll", "we're", "we've", "welcome", "well", "went", "were", "weren't", "what", "what's", "whatever", "when", "whence", "whenever", "where", "where's", "whereafter", "whereas", "whereby", "wherein", "whereupon", "wherever", "whether", "which", "while", "whither", "who", "who's", "whoever", "whole", "whom", "whose", "why", "will", "willing", "wish", "with", "within", "without", "won't", "wonder", "would", "would", "wouldn't", "x", "y", "yes", "yet", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves", "z", "zero"
- toont geen deels zoekwoorden (zoekwoord moet 4 of meer dan 4 karakters bevatten)
- toont geen resultaat als de match met het een zoekwoord minder dan 3 of gelijk is aan 3 karakters
- toont geen resultaat als het zoekwoord in meer dan 50% van de rijen gevonden is
- toont geen resultaat als het zoekwoord is gevonden in de 'stop lijst'
- toont geen resultaat als het zoekwoord een hyperante is (zoals: ex-man omdat de woorden ex en man appart bekeken worden), maar extra-werknemer weer wel omdat extra meer dan 4 karakters is en werknemer ook.
- de resultaten zijn op relevantie, descending
De woorden in de stoplijst zitten ergens diep verborgen in MySQL. De stopwoorden kunnen verschillen per MySQL versie. Het is dus verstandig om de stopwoorden op te zoeken per MySQL versie. Hier zijn de stopwoorden:
"a", "a's", "able", "about", "above", "according", "accordingly", "across", "actually", "after", "afterwards", "again", "against", "ain't", "all", "allow", "allows", "almost", "alone", "along", "already", "also", "although", "always", "am", "among", "amongst", "an", "and", "another", "any", "anybody", "anyhow", "anyone", "anything", "anyway", "anyways", "anywhere", "apart", "appear", "appreciate", "appropriate", "are", "aren't", "around", "as", "aside", "ask", "asking", "associated", "at", "available", "away", "awfully", "b", "be", "became", "because", "become", "becomes", "becoming", "been", "before", "beforehand", "behind", "being", "believe", "below", "beside", "besides", "best", "better", "between", "beyond", "both", "brief", "but", "by", "c", "c'mon", "c's", "came", "can", "can't", "cannot", "cant", "cause", "causes", "certain", "certainly", "changes", "clearly", "co", "com", "come", "comes", "concerning", "consequently", "consider", "considering", "contain", "containing", "contains", "corresponding", "could", "couldn't", "course", "currently", "d", "definitely", "described", "despite", "did", "didn't", "different", "do", "does", "doesn't", "doing", "don't", "done", "down", "downwards", "during", "e", "each", "edu", "eg", "eight", "either", "else", "elsewhere", "enough", "entirely", "especially", "et", "etc", "even", "ever", "every", "everybody", "everyone", "everything", "everywhere", "ex", "exactly", "example", "except", "f", "far", "few", "fifth", "first", "five", "followed", "following", "follows", "for", "former", "formerly", "forth", "four", "from", "further", "furthermore", "g", "get", "gets", "getting", "given", "gives", "go", "goes", "going", "gone", "got", "gotten", "greetings", "h", "had", "hadn't", "happens", "hardly", "has", "hasn't", "have", "haven't", "having", "he", "he's", "hello", "help", "hence", "her", "here", "here's", "hereafter", "hereby", "herein", "hereupon", "hers", "herself", "hi", "him", "himself", "his", "hither", "hopefully", "how", "howbeit", "however", "i", "i'd", "i'll", "i'm", "i've", "ie", "if", "ignored", "immediate", "in", "inasmuch", "inc", "indeed", "indicate", "indicated", "indicates", "inner", "insofar", "instead", "into", "inward", "is", "isn't", "it", "it'd", "it'll", "it's", "its", "itself", "j", "just", "k", "keep", "keeps", "kept", "know", "knows", "known", "l", "last", "lately", "later", "latter", "latterly", "least", "less", "lest", "let", "let's", "like", "liked", "likely", "little", "look", "looking", "looks", "ltd", "m", "mainly", "many", "may", "maybe", "me", "mean", "meanwhile", "merely", "might", "more", "moreover", "most", "mostly", "much", "must", "my", "myself", "n", "name", "namely", "nd", "near", "nearly", "necessary", "need", "needs", "neither", "never", "nevertheless", "new", "next", "nine", "no", "nobody", "non", "none", "noone", "nor", "normally", "not", "nothing", "novel", "now", "nowhere", "o", "obviously", "of", "off", "often", "oh", "ok", "okay", "old", "on", "once", "one", "ones", "only", "onto", "or", "other", "others", "otherwise", "ought", "our", "ours", "ourselves", "out", "outside", "over", "overall", "own", "p", "particular", "particularly", "per", "perhaps", "placed", "please", "plus", "possible", "presumably", "probably", "provides", "q", "que", "quite", "qv", "r", "rather", "rd", "re", "really", "reasonably", "regarding", "regardless", "regards", "relatively", "respectively", "right", "s", "said", "same", "saw", "say", "saying", "says", "second", "secondly", "see", "seeing", "seem", "seemed", "seeming", "seems", "seen", "self", "selves", "sensible", "sent", "serious", "seriously", "seven", "several", "shall", "she", "should", "shouldn't", "since", "six", "so", "some", "somebody", "somehow", "someone", "something", "sometime", "sometimes", "somewhat", "somewhere", "soon", "sorry", "specified", "specify", "specifying", "still", "sub", "such", "sup", "sure", "t", "t's", "take", "taken", "tell", "tends", "th", "than", "thank", "thanks", "thanx", "that", "that's", "thats", "the", "their", "theirs", "them", "themselves", "then", "thence", "there", "there's", "thereafter", "thereby", "therefore", "therein", "theres", "thereupon", "these", "they", "they'd", "they'll", "they're", "they've", "think", "third", "this", "thorough", "thoroughly", "those", "though", "three", "through", "throughout", "thru", "thus", "to", "together", "too", "took", "toward", "towards", "tried", "tries", "truly", "try", "trying", "twice", "two", "u", "un", "under", "unfortunately", "unless", "unlikely", "until", "unto", "up", "upon", "us", "use", "used", "useful", "uses", "using", "usually", "v", "value", "various", "very", "via", "viz", "vs", "w", "want", "wants", "was", "wasn't", "way", "we", "we'd", "we'll", "we're", "we've", "welcome", "well", "went", "were", "weren't", "what", "what's", "whatever", "when", "whence", "whenever", "where", "where's", "whereafter", "whereas", "whereby", "wherein", "whereupon", "wherever", "whether", "which", "while", "whither", "who", "who's", "whoever", "whole", "whom", "whose", "why", "will", "willing", "wish", "with", "within", "without", "won't", "wonder", "would", "would", "wouldn't", "x", "y", "yes", "yet", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves", "z", "zero"
Reacties
0