Equivalent searching using "like" with "match()" - mysql

I have a query like this:
SELECT * FROM table WHERE col LIKE '%word'
Now what is its the equivalent of above query in fulltext indexed?
It should be noted that this does note work:
SELECT * FROM table WHERE MATCH(col) AGAINST('+word' IN BOOLEAN MODE)
EDIT
I want to select 'test' in this sentence:
it is a ttest.

I don't think MySQL directly supports this. You can speed the query by doing:
SELECT t.*
FROM (SELECT *
FROM table
WHERE MATCH(col) AGAINST('+word' IN BOOLEAN MODE)
) t
WHERE col LIKE '%word';
(I'm not 100% sure that the subquery is needed.)
If you know that this will be a common type of search, you can hack a solution. Modify each of the documents to be something like:
BEGINDOCMARKER blah blah blah ENDDOCMARKER
Then you can search for:
SELECT *
FROM table
WHERE MATCH(col) AGAINST('"word ENDDOCMARKER"' IN BOOLEAN MODE)
If you do take this approach, be careful with the marker. It is tempting to use ^ and $ (ala regular expressions), but these will be unindexed due to the minimum word length and other reasons. Some uncommon jumble of characters is a good bet.
Also note that this makes the text longer and you will probably want to remove these words for presentation purposes. If space is not an issue, duplicate the field, one for searching and one for presenting. This can be useful for another reason: handling synonyms. Or, consider other text search alternatives. Other tools do allow positioning information in the query.

Related

MyIsam fulltext search against multiple %term%

I have a field called filepath that I'm trying to search. Here is an example path:
/mnt/qfs-X/Asset_Management/XG_Marketing_/Episodic-SG_1001_1233.jpg
I would like to be able to search the following and get a match:
search = "qf episodic sg_1001 JPG"
How would I do this with a fulltext search in mysql/myisam? What I have now is:
SELECT * FROM x_files2 WHERE MATCH(path)
AGAINST('qf episodic sg_1001 JPG' in boolean mode)
But it is returning way too many results (seems like it's returning if any terms are found instead of only those where all are found.
Put + in front of each 'word':
AGAINST('+qf* +episodic +sg_1001* +JPG' in boolean mode)
Do you have the min-word-length set to 2? If not, there could be other troubles.
The + avoids "too many".
Consider switching to InnoDB, now that it has FULLTEXT.
You may have to abandon use of FULLTEXT and switch to LIKE:
WHERE path LIKE '%qf%episodic%sg_1001%JPG%'
If performance is an issue, consider something like
WHERE MATCH(path) AGAINST('...' IN BOOLEAN MODE) -- using some of the words
AND path LIKE '...' -- as above
The MATCH will run first, whittling down the number of possible rows considerably, then the LIKE takes care of details.
Note that middles of words cannot be used in AGAINST. Those could be left out, relying on LIKE to take care of them.

Using Fulltext in MYSQL, are wildcards expensive?

I am working on a MySQL search query where I would like incomplete strings to find matches such as:
Search term: "Fi Res", which should find: "Find Result".
I have found a few related questions that tend to answer "use Fulltext". Simply using fulltext doesn't match partial terms, but it seems to work with wildcards, so this (appears to) work:
SELECT * FROM `table` WHERE MATCH (field) AGAINST ('Fi*Res*' IN BOOLEAN MODE)
And a quick solution seems to be just replace the spaces in a query with *.
I'm wondering if there's some reason not to do this, and if so, what (better) implementations should I be looking at?
Also, in this case it's a smaller database table (< 20,000 rows) and the strings to be searched are short (max 255 length).
Wildcards are just substitution of words in 'values' u r searching.. for example google search is kind of wildcard. so u can use '%' wild card for searching..!

How to use prefix wildcards like '*abc' with match-against

I have the following query :
SELECT * FROM `user`
WHERE MATCH (user_login) AGAINST ('supriya*' IN BOOLEAN MODE)
Which outputs all the records starting with 'supriya'.
Now I want something that will find all the records ending with e.g. 'abc'.
I know that * cannot be preappended and it doesn't work either and I have searched a lot but couldn't find anything regarding this.
If I give query the string priya ..it should return all records ending with priya.
How do I do this?
Match doesn't work with starting wildcards, so matching with *abc* won't work. You will have to use LIKE to achieve this:
SELECT * FROM user WHERE user_login LIKE '%abc';
This will be very slow however.
If you really need to match for the ending of the string, and you have to do this often while the performance is killing you, a solution would be to create a separate column in which you reverse the strings, so you got:
user_login user_login_rev
xyzabc cbazyx
Then, instead of looking for '%abc', you can look for 'cba%' which is much faster if the column is indexed. And you can again use MATCH if you like to search for 'cba*'. You will just have to reverse the search string as well.
I believe the selection of FULL-TEXT Searching isn't relevant here. If you are interested in searching some fields based on wildcards like:
%word% ( word anywhere in the string)
word% ( starting with word)
%word ( ending with word)
best option is to use LIKE clause as GolezTrol has mentioned.
However, if you are interested in advanced/text based searching, FULL-TEXT search is the option.
Limitations with LIKE:
There are some limitations with this clause. Let suppose you use something like '%good' (anything ending with good). It may return irrelevant results like goods, goody.
So make sure you understand what you are doing and what is required.

Boolean search with truncated exclutions words don't work for me

When I search for:
SELECT * FROM db.test
WHERE
MATCH(story)AGAINST('(+bananas -banana*)'IN BOOLEAN MODE)
I get rows returned but when I search for
SELECT * FROM db.test
WHERE
MATCH(story)AGAINST('(+bananas -bananas)'IN BOOLEAN MODE)
or
SELECT * FROM db.test
WHERE
MATCH(story)AGAINST('(+bananas -bananas*)'IN BOOLEAN MODE)
I get no result. To me it seems like you canĀ“t use * together with the minus sign.
Does anybody know if thats the case or if its a setting in MySql.
Kind regards
Olle
The table is MYISAM and I have a index on the column story.
The last 2 queries do not give any result because they contain contradicting conditions - story must have the word "bananas" and must not have the word "bananas". This is not possible and hence no results.
However the first query means that "bananas" must be present but no "banana".
Also, you may use * with the minus operator.
Hope this helps.
The solution is to skip the parentheses. If I search for '+bananas -banana*' instead of '(+bananas -banana*)' it works. It took a while to figure out thou.
Cheers

Is it possible to stem full text match queries in MySql

I'm trying to use wildcards to pass a stem of a word as part of a full text search in MySql. I would prefer to use match...against for the performance benefit instead of a like query.
I found this post which makes it sound as though this can be done:
MySQL fulltext with stems
...but I can't get it to work for me.
My data looks like this:
table name: "rxnorm_brands"
step_medname bn_name
Amoxicillin Wymox
Amoxicillin-Clavulanate Augmentin
This query works but uses "like":
select `step_medname`, `bn_name`
from `rxnorm_brands`
where (`bn_name` like 'Amox%' or `step_medname` like 'Amox%');
I want to use this query, but it returns nothing:
select `step_medname`, `bn_name`
from `rxnorm_brands`
where MATCH (`bn_name`, `step_medname`) AGAINST ('Amox*');
I do have a fulltext index on bn_name and step_medname. What am I doing wrong? Or can this not be done?
This can be done using IN BOOLEAN MODE, see: http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.html.
So your query would become:
select `step_medname`, `bn_name`
from `rxnorm_brands`
where MATCH (`bn_name`, `step_medname`) AGAINST ('Amox*' IN BOOLEAN MODE);
but note that with the BOOLEAN MODE matching, rows either match or they don't - the results can no longer be ordered by relevance like they can with normal FULLTEXT searches.
The RxNorm API now has a method that will do matching of text that only approximately matches the RxNorm concept. See http://rxnav.nlm.nih.gov/RxNormAPI.html#label:23