MySQL query BOOLEAN MODE Case Sensitivity - mysql

My search is case sensitive, but I want it to be case insensitive. In MySQL I have my database and table set to utf8_general_ci. The search is still case sensitive. I have been doing some research and it seems the reason behind this is BOOLEAN MODE in my query. Is there a way to make it case insensitive? so no matter how I type any word with any sensitivity it will always bring it up in the search result?
SELECT
s_cost_sheet.partnumber,
s_cost_sheet.description,
s_cost_sheet.price,
s_cost_sheet.notes
FROM s_cost_sheet
WHERE MATCH ( partnumber, description, price, notes )
AGAINST('%".$search."%' IN BOOLEAN MODE) ORDER BY partnumber, description, price, notes ASC";
I have tested the search in phpMyAdmin and it works no matter how a type the word plate, it can be Plate, PLATE, plaTE. It all works fine, so it must be something within this that is causing the issue.

If one of the columns is of type int or numeric then the search becomes case sensitive. Also there's no need to use % in the searched string

TRY changing your table and column to utf8_general_ci and you don't have to use % wildcard with FULL TEXT Search
RECOMMENDATIONS
Also avoid using a lot of columns with ORDER BY clause if you need quicker results.

Related

How to make a search match even though the searched string isn't exact in Mysql

I am used to work with Postgres. With postgres I was able to make a more "intelligent search" by installing the pg_trgm trigram extension and then the user could miss a letter like "aple" or position the letters wrong "appel" that the search would match. With Mysql I don't know which feature to use. I can someone give a direction?
My query is like this:
select *,
case when titulo like '%pneu%' then 1 else 0 end as rank_titulo,
case when descricao like '%pneu%' then 1 else 0 end as rank_descricao,
case when tag like '%pneu%' then 1 else 0 end as rank_tag
from produto where titulo like '%pneu%'
or descricao like '%pneu%' or
tag like '%pneu%' order by rank_titulo desc, rank_descricao desc,
rank_tag desc ;
I don't care if the user typed "pineu", "pneo", "penu" that search should match.
I don't want a working code that solve my problem, I just want to know the feature that I should use, some demo code would be appreciated.
The nearest MySQL feature to postgreSQL's trigram extension is FULLTEXT searching.
You might use this syntax.
...WHERE MATCH(titulo, descricao, tag) AGAINST('pneu' IN NATURAL LANGUAGE MODE)...
You need a FULLTEXT index in your table to make this work.
CREATE FULLTEXT INDEX ft ON produto(titulo, descricao, tag);
Beware a couple of things: FULLTEXT only works on words of three letters or more by default, and natural language mode works strangely on small tables. You can change these things. You may also need to add stopwords in your language (Portuguese?).
Also beware that it often works counterintuitively. You may find yourself asking "why did it do that?" quite often.

*Actual* exact MySQL fulltext search

So I'm having some difficulty creating exact searches in MySQL fulltext.
In my database, I'm trying to find jobs with a specific keyword in its title.
So I might try
WHERE MATCH(jobTitle) AGAINST ('"fs sales"' IN BOOLEAN MODE)
However, this finds matches on "sales", not "fs sales"
How can I ensure that "fs sales" matches EXACTLY on "fs sales" and not "sales"?
Table is InnoDB for reference.
"fs" is probably excluded from the search as too short.
Check the value of innodb_ft_min_token_size and manual: https://dev.mysql.com/doc/refman/5.6/en/fulltext-fine-tuning.html
You have to rebuild the index after changing that variable.
Your query should work. My guess, though is that you did not change the minimum word length, so "fs" was never indexed. See here for information on this.
Other possibilities are that there are other characters in the text, perhaps characters you do not see.
You might try this
select t.*
from (select . . .
WHERE MATCH(jobTitle) AGAINST ('+fs +sales' IN BOOLEAN MODE)
) t
where jobTitle like '%fs sales%';
This only does the like on the returned set from the match.
However, my best guess is that innodb_ft_min_token_size is set to its default value of 3, so "fs" is not being indexed.
you can do it like
select col1, col2 from table_name where text_column like '%fs sales%'
this will return all the records having fs sales in them..

mysql fulltext boolean search with asterix

I have a query like below:
SELECT prd_id FROM products WHERE MATCH (prd_search_field)
AGAINST ('+gul* +yetistiren* +adam*' in boolean mode);
This doesn't return the rows including 'gul'.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html
The document says this.
Then a search for '+word +the*' will likely return fewer rows than a
search for '+word +the':
The former query remains as is and requires both word and the* (a word starting with the) to be present in the document.
The latter query is transformed to +word (requiring only word to be present). the is both too short and a stopword, and either condition is enough to cause it to be ignored.
So as I understood the too short word condition must not be applied in my situation since I use * after each word. What's wrong with this?
As a solution I use the below query but since it's slow, I need to find another solution. Any idea would be appreciated? Thanks in advance..
SELECT prd_id FROM products WHERE 1 AND MATCH (prd_search_field)
AGAINST ('+yetistiren* +adam*' in boolean mode) AND prd_search_field
LIKE '%gul%';
As a note ft_min_word_length=4 as default in all shared hosting environments, and I cannot change it.

MySQL full text index underscore

I have a problem with MySQL's full text index, it treats underscore as part of a word (why? dunno).
This is the string I have in my table, VA_-_Some_Album
And this is the query for it:
SELECT
*
FROM
`mytable`
WHERE
MATCH (`name`) AGAINST ('+Some* +Album*' IN BOOLEAN MODE)
ORDER BY `sdate` DESC
LIMIT 3
MySQL returns an empty set for this query, unless I change it to +*Some* since the underscore is part of the word (_Some instead of Some). This is not good for me, since when adding the extra asterisk (*) the plus sign stops functioning and I don't get the "AND" done.
I tried to change the charset definition, and rebuild the full-text index but nothing.
Any ideas? changing the way the string is stored is not up to me.
Thank you!
I'm not very clear with your question but take a look here:
http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html
there they explain the differences between _, +, *, -, <>, etc In Boolean Mode

mysql boolean mode fulltext search with wildcards and literals

I'm pretty new to MySQL full-text searches and I ran into this problem today:
My company table has a record with "e-magazine AG" in the name column. I have a full-text index on the name column.
When I execute this query the record is not found:
SELECT id, name FROM company WHERE MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE);
I need to work with quotes because of the dash and to use the wildcard because I implement a "search as you type" functionality.
When I search for the whole term "e-magazine AG", the record is found.
Any ideas what I'm doing wrong here? I read about adding the dash to the list of word characters (config update needed) but I'm searching for a way to do this programmatically.
This clause
MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE);
Will search for a AND "e" AND NOT "magazi"; i.e. the - inside "e-magazi" will be interpreted as a not even though it is inside quotation marks.
For this reason it will not work as expected.
A solution is to apply an extra having clause with a LIKE.
I know this having is slow, but it will only be applied to the results of the match, so not too many rows should be involved.
I suggest something like:
SELECT id, name
FROM company
WHERE MATCH(name) AGAINST('magazine' IN BOOLEAN MODE)
HAVING name LIKE '%e-magazi%';
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)