full-text-searchmariadbfulltext-index

MariaDB fulltext search with special chars and "word starts with"


I can do a MariaDB fulltext query which searches for the word beginning like this:

select * from mytable
where match(mycol) against ('+test*' in boolean mode)>0.0;

This finds words like "test", "tester", "testing".

If my search string contains special characters, I can put the search string in quotes:

select * from mytable
where match(mycol) against ('+"test-server"' in boolean mode)>0.0;

This will find all rows which contain the string test-server.

But it seems I cannot combine both:

select * from mytable
where match(mycol) against ('+"test-serv"*' in boolean mode)>0.0;

This results in an error:

Error: (conn:7) syntax error, unexpected $end, expecting FTS_TERM or FTS_NUMB or '*'
SQLState:  42000
ErrorCode: 1064

Placing the ´*´ in the quoted string will return no results (as expected):

select * from mytable
where match(mycol) against ('+"test-serv*"' in boolean mode)>0.0;

Does anybody know whether this is a limitation of MariaDB? Or a bug?

My MariaDB version is 10.0.31


Solution

  • WHERE MATCH(mycol) AGAINST('+test +serv*' IN BOOLEAN MODE)
      AND mycol LIKE '%test_serv%'
    

    The MATCH will find the desired rows plus some that are not desired. Then the LIKE will filter out the duds. Since the LIKE is being applied to only some rows, its slowness is masked.

    (Granted, this does not work in all cases. And it requires some manual manipulation.)

    d'Artagnan - Use

    WHERE MATCH(mycol) AGAINST("+Arta*" IN BOOLEAN MODE)
      AND mycol LIKE '%d\'Artagnan%'
    

    Note that I used the suitable escaping for getting the apostrophe into the LIKE string.

    So, the algorithm for your code goes something like:

    1. Break the string into "words" the same way FULLTEXT would.
    2. Toss any strings that are too short.
    3. If no words are left, then you cannot use FULLTEXT and are stuck with a slow LIKE.
    4. Stick * after the last word (or each word?).
    5. Build the AGAINST with those word(s).
    6. Add on AND LIKE '%...%' with the original phrase, suitably escaped.