MySQL fulltext treats the word e-magazine
in a text as a phrase and not as a word. Because of that it results the two words e
and magazine
. And while it builds the search index it does not add the e
to the index because of the ft_min_word_len
(default is 4 chars).
The same length limitation is used for the search query. That is the reason why a search for e-magazine
returns exactly the same results as a-magazine
because a
and -
is fully ignored.
But now you want to find the exact phrase e-magazine
. By that you use the quotes and that is the complete correct way to find phrases, but MySQL does not support operators for phrases, only for words:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html
With this modifier, certain characters have special meaning at the beginning or end of words in the search string
Some people would suggest to use the following query:
SELECT id, name
FROM company
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE)
HAVING name LIKE 'e-magazi%';
As I said MySQL ignores the e-
and searches for the wildcard word magazi*
. After those results are optained it uses HAVING
to aditionally filter the results for e-magazi*
including the e-
. By that you will find the phrase e-magazine AG
. Of course HAVING
is only needed if the search phrase contains the wildcard operator and you should never use quotes. This operator is used by your user and not you!
Note: As long you do not surround the search phrase with %
it will find only fields that start with that word. And you do not want to surround it, because it would find bee-magazine
as well. So maybe you need an additional OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%'
to make it usable inside of texts.
Trick
But finally I prefer a trick so HAVING
isn't needed at all:
- If you add texts to your database table, add them additionally to a separate fulltext indexed column and replace words like
up-to-date
with up-to-date uptodate
.
- If a user searches for
up-to-date
replace it in the query with uptodate
.
By that you can still find specific
in user-specific
but up-to-date
as well (and not only date
).
Bonus
If a user searches for -well-known huge ports
MySQL treats that as not include *well*, could include *known* and *huge*
. Of course you could solve that with an other extra query variant as well, but with the trick above you remove the hyphen so the search query looks simply like that:
SELECT id
FROM texts
WHERE MATCH(text) AGAINST('-wellknown huge ports' IN BOOLEAN MODE)
SELECT id, bootid FROM socket WHERE MATCH(bootid) AGAINST('+"18bda775"' IN BOOLEAN MODE);
will work and so will if i search for "18bda775-711c", but searching for "18bda" or "18bda775-711" won't work. thebootid
field in question contains: 18bda775-711c-4329-9de2-a3d81dc13d06 – Futilityft_boolean_syntax=+ #><()~*:""&|
– Numerable