I have a fulltext index on a number of columns and i'm trying to do a MATCH AGAINST IN BOOLEAN MODE on those columns, trying to find an email address. Here are the results:
if i search for "test#email.com" (with quotes) - the query returns correct results
if i search for "a#b.com" (with quotes) - the query does not return anything
Can someone tell me why a short email a#b.com does not get returned and how would i solve this?
Here's the query i'm using:
SELECT MATCH(email, phone, title, description) AGAINST('"a#b.com"' IN BOOLEAN MODE) AS score
FROM thetable WHERE MATCH(email, phone, title, description)
AGAINST('"a#b.com"' IN BOOLEAN MODE) ORDER BY `status` DESC, score DESC
This is a combination of two problems:
# isn't considered being a 'word character', and neither is -, so searching for a#b.com actually comes down to searching for words a, b and com
a and b are shorter than ft_min_word_len
The solution would be to make # and . being considered word characters. There are several methods listed on http://dev.mysql.com/doc/refman/5.6/en/fulltext-fine-tuning.html
The most practical one would be adding a custom collation as described in
http://dev.mysql.com/doc/refman/5.6/en/full-text-adding-collation.html
Update:
a)You need to set ft_min_word_len = 1 in my.cnf.
b) Output of show variables
ft_min_word_len | 1
c) Fired below query:
mysql> SELECT name,email FROM jos_users WHERE MATCH (email) AGAINST ('a#b.com') limit 1;
+--------+---------+
| name | email |
+--------+---------+
| kap | a#b.com |
+--------+---------+
1 row in set (0.00 sec)
Hope this will help.
~K
I think you need to change ft_min_word_len
As specified in MySQLdoc fine tuning
The minimum and maximum lengths of words to be indexed are defined by
the ft_min_word_len and ft_max_word_len system variables. (See
Section 5.1.4, “Server System Variables”.) The default minimum value
is four characters; the default maximum is version dependent. If you
change either value, you must rebuild your FULLTEXT indexes. For
example, if you want three-character words to be searchable, you can
set the ft_min_word_len variable by putting the following lines in an
option file:
[mysqld]
ft_min_word_len=3
Then restart the server and rebuild your FULLTEXT indexes. Note particularly the remarks regarding myisamchk in the instructions
following this list.
Related
I'm in trouble with a strange behavior of mysql.
If I try to search with fulltext query sam* word, I have no results back.
Ex. table companies
id || name
1 || Company name
2 || Same Company name
If I make
`SELECT name FROM companies WHERE MATCH name AGAINST ('+Company*' IN BOOLEAN MODE)`
It works, instead if I use
`SELECT name FROM companies WHERE MATCH name AGAINST ('+Sam*' IN BOOLEAN MODE)`
or
`SELECT name FROM companies WHERE MATCH name AGAINST ('+Same' IN BOOLEAN MODE)`
I have no results!
Do you have any idea about this issue?
PS. if I use +Sa* instead of +Sam*, it works
You must to change the configuration value ft_min_word_len (fulltext min word length) the default value is set to 4.
Add (or modify) this line to mysql config /etc/my.cnf (or my.ini in windows)
ft_min_word_len = 3
After that you may call the index re-creation using the command:
REPAIR TABLE companies QUICK;
BTW: Fulltext search doesn't accept LIKE wildcards: * or %
I have the following query:
SELECT * FROM products WHERE is_active = 1 AND MATCH (full_text) AGAINST ('М 1050' IN BOOLEAN MODE)
This query returns two records, here's the full_index column contents of both:
; 013 001 106 ; Ъглошлайф SPARKY M 1050 HD ; 1050W,10000об.,ф125мм
; SPARKY ; 69 ; ; 040 070 1050 ; Вложка дванадесетограм удължена ;
1/4" 5мм FORSE /5295005/ ; FORCE ; 77 ;
But I want only the first row, I don't need the second one. What's wrong?
In addition to the answer provided by user144590; M is not, by default, considered a word.
From the docs
Any word that is too short is ignored. The default minimum length of words that are found by full-text searches is three characters for InnoDB search indexes, or four characters for MyISAM. You can control the cutoff by setting a configuration option before creating the index: innodb_ft_min_token_size configuration option for InnoDB search indexes, or ft_min_word_len for MyISAM.
UPDATE
Without changing the minimum length I guess you'd have to replace (in the column data) the space in the text 'M 1050' with another word character like '_' and match against 'M_1050' (in the query), or run a much slower LIKE '%M 1050%' condition.
Based on http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html
Note
In implementing this feature, MySQL uses what is sometimes referred to as implied Boolean logic, in which
plus(+) stands for AND
minus(-) stands for NOT
[no operator] implies OR
So essentially you are doing an OR, if you need both the terms use + as such
SELECT * FROM products WHERE is_active = 1 AND MATCH (full_text) AGAINST ('+М +1050' IN BOOLEAN MODE)
If you want to match some words exactly, use double quotations mark (e.g '"М 1050"')
SELECT * FROM products WHERE is_active = 1 AND MATCH (full_text) AGAINST ('"М 1050"' IN BOOLEAN MODE)
Table
id name
--- ------
1 chinu
2 sanjib
3 chinmay
My MYSQL Query
SELECT * FROM users WHERE MATCH (name) AGAINST ('chi' IN BOOLEAN MODE)
In above query i am getting 0 record.
My output will be coming
1 chinu
3 chinmay
How to get my actual record using MATCH...AGAINST query?
EDIT - If i am searching chinu instead of chi i am getting 1 record.
You need to add an asterisk to the 'chi' to indicate that the query should match against all that contain the string and not just the string itself. Just using the string 'chi' will only match exactly 'chi' for example.
change your query to read
SELECT * FROM users WHERE MATCH (name) AGAINST ('chi*' IN BOOLEAN MODE)
and you should get the results you expect.
I think you forgot the + sign:
SELECT * FROM users WHERE MATCH (name) AGAINST ('+chi' IN BOOLEAN MODE)
Or if it is an exact phrase, use double quotes to surround the string:
SELECT * FROM users WHERE MATCH (name) AGAINST ('"chi"' IN BOOLEAN MODE)
I am the first to admit that this is not easy to find. MySQL full text search uses a system variable called ft_min_word_length. The default value is 4, as shown here.
Because you are searching for a 3-character word, it is not being indexed. Hence it is not found.
More information is available in the documentation on fine tuning the search. But the basic idea is that you need to change the value of the parameter and rebuild the index.
For your particular query, though, you just need to include wildcards, as explained in other answers.
I have a MyISAM table named links. It has a column searcher which has a FULLTEXT index to it.
This is my variable values:
ft_min_word_len = 1
ft_stopword_file =
ft_max_word_len = 84
I need to match the rows which contain both [show] & [1] in any order.
I run this query:
SELECT * FROM links WHERE MATCH(searcher) AGAINST('+[show] +[1]' IN BOOLEAN MODE)
But it is also matching the rows that don't contain [1] string. Whats the problem?
It seems that you have to make clear that the brackets are part of the search string and not part of syntax for grouping expressions.
This query should work for you:
SELECT * FROM links WHERE MATCH(searcher) AGAINST('+"[show]" +"[1]"' IN BOOLEAN MODE)
Here are some sample fiddles:
not working
working
I have MySQL db, db engine InnoDB, collation set to utf8-utf8_general_ci (also tried utf8_unicode_ci). I would like db to treat equaly č and c, ž and z, ć and c, š and s, đ and d.
E.g,
table1
-------------
id | name
-------------
1 | mačka
2 | đemper
-------------
if I run query:
SELECT * FROM table1 WHERE name LIKE '%mac%'
or
SELECT * FROM table1 WHERE name LIKE '%mač%'
I will get the result:
-------------
id | name
-------------
1 | mačka
Which is OK, that is exactly what I want.
But if run query:
SELECT * FROM table1 WHERE name LIKE '%de%'
I get zero results.
And if I run query:
SELECT * FROM table1 WHERE name LIKE '%đe%'
I will get:
-------------
id | name
-------------
2 | đemper
This is not behaviour that i would want nor expect. I would like that both (last two queries) returned:
-------------
id | name
-------------
2 | đemper
How can I accomplish this?
Any kind of help is appreciated, thanks in advance :) !
This can't be done without the use of regular expressions, as there is no collation in MySQL that considers đ equivalent to d.
The collation you are using determines things like this -- what characters are considered 'equal', and what order they should sort in. But first off, you need to know what encoding your table is using.
The command SHOW TABLE STATUS LIKE 'table1'\G should show you that. That will help you determine the collation you need to use.
If it's Unicode (UTF8, e.g.), then you need to set a Unicode collation. There doesn't appear to be one built-in to MySQL for Croatian. You can check the MySQL Character Set manual page to see if anything there is going to be 'close enough'.
If it's iso-latin-2 (iso-8859-2), then you can use 'latin2_croatian_ci' collation.
If it's CP-1250, then there is also a 'cp1250_croatian_ci' collation.
The non-unicode collations are in the manual here.
EDIT
As Ignacio Vazquez-Abrams correctly points out, none of the MySQL collations consider 'đ' to be equivalent to 'd'. (Reference for MySQL collations)
If you are really eager to put a lot of time into this, you can also read up on how to install your own custom collation