MySQL Full Text Search Not Matching - mysql

My MySQL table is not returning results with a MATCH (col) AGAINST ('') query.
The table is simple:
id | url | fullTextIndex
And my query is
SELECT *, Match(fullTextIndex) AGAINST ("7f7f7f807f8080807f8080807f7f7f807c828888808a86967e8b858d7f89838a76829e958f7badb68084a3a38384899077848b877f799f9c85799fa2827d8c8a ") FROM Pictures;
The last column, the match, is always 0. Except, I know for a fact that the string above is contained, verbatim, in one of the values.
Things to note:
The string is only in that row (so it is not in more than 50% of rows, so it shouldn't be ignored).
This is not the Full value
The column is a bigText column
When I use INSTR, I get the value 1 (which is correct)
Any ideas why this query might not be working?

There seems to be a (configurable) upper limitation on the length of the words considered for indexation:
http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_ft_max_word_len
You can check the current value with SHOW VARIABLES LIKE "ft_max_word_len";
It returns 84 on my server, and your string is 128 chars long.
Suggested fix:
Add this line to your my.cnf file: ft_max_word_len=128 (or whatever max length you need)
Rebuild your indexes as advised on the MySQL website: REPAIR TABLE tbl_name QUICK;

Related

Maria DB - Prevent removal of trailing white space in where clause

MariaDB version 10.3.22 and 10.3.23
I have a table with column name entries like these. The second entry contains trailing spaces. Datatype of the column is Varchar(50)
"John"
"John "
I want the below query to return only the first entry, but it returns both entries. Seems like internally, it's doing the trim while comparing. Any way to perform the exact match
Select name from <table> where name="John";
Similarly, the below query should not return any rows as I'm trying to match with extra space, but it outputs two rows. Some behind the scene trimming is happening. Need to either disable it or anyway to do the exact match
Select name from <table> where name="John ";
Use the BINARY option to compare exactly rather than as strings.
Select name from <table> where BINARY name="John";

Problems with Boolean search mode in mysql FULLTEXT INDEX

I have a problem with the Boolean search method in MySql. I am not getting out of this.
I have 3 columns, set as VARCHAR, where I have in two columns only words and in the third column also numbers. I use the plus operator so that any given search word must be contained in the returning row.
But, when it comes to the numbers, I always get an empty result.
The query below returns an empty set, even if the number 2 is contained in the col3!
What is the problem?
My query:
SELECT * FROM table WHERE MATCH (col1, col2, col3) AGAINST ('+apache +httpd +2' IN BOOLEAN MODE)
Here is a piece of sample data. But I understand now why it is not returning anything. Thank you for this.
The format below exportet from SQL Database ist JSON, {"colum_name":"colum_data"}
{"reverse_dns":"net-2-32-38-169.cust.vodafonedsl.it","protocol":"tcp","port":"443","state":"open","service":"http","product":"Microsoft IIS httpd","version":"10.0","extrainfo":"","cpe":"cpe:\/a:microsoft:iis:10.0","scantime":"1591110220","timestamp":"2020-07-16 17:41:32","id":"200150","tunnel":"ssl","ip_address":"2.323.81.69","hostname":""}

Select statement returns data although given value in the where clause is false

I have a table on my MySQL db named membertable. The table consists of two fields which are memberid and membername. The memberid field has the type of integer and uses auto_increment function starting from 2001. The membername table has the type of varchar.
The membertable has two records with the same order as described above. The records look like this :
memberid : 2001
membername : john smith
memberid : 2002
membername : will smith
I found something weird when I ran a SELECT statement against the memberid field. Running the following statement :
SELECT * FROM `membertable` WHERE `memberid` = '2001somecharacter'
It returned the first data.
Why did that happen? There's no record with memberid = 2001somecharacter. It looks like MySQL only search the first 4 character (2001) and when It's found related data, which is the returned data above, it denies the remaining characters.
How could this happen? And is there any way to turn off this behavior?
--
membertable uses innodb engine
This happens because mysql tries to convert "2001somecharacter" into a number which returns 2001.
Since you're comparing a number to a string, you should use
SELECT * FROM `membertable` WHERE CONVERT(`memberid`,CHAR) = '2001somecharacter';
to avoid this behavior.
OR to do it properly, is NOT put your search variable in quotes so that it has to be a number otherwise it'll blow up because of syntax error and then in front end making sure it's a number before passing in the query.
sqlfiddle
Your finding is an expexted MySQL behaviour.
MySQL converts a varchar to an integer starting from the beginning. As long as there are numeric characters wich can easily be converted, they are icluded in the conversion process. If there's a letter, the conversion stops returning the integer value of the numeric string read so far...
Here's some description of this behavior on the MySQL documentation Site. Unfortunately, it's not mentioned directly in the text, but there's an example which exactly shows this behaviour.
MySQL is very liberal in converting string values to numeric values when evaluated in numeric context.
As a demonstration, adding 0 causes the string to evaluated in a numeric context:
SELECT '2001foo' + 0 --> 2001
, '01.2-3E' + 0 --> 1.2
, 'abc567g' + 0 --> 0
When a string is evaluated in a numeric context, MySQL reads the string character by character, until it encounters a character where the string can no longer be interpreted as a numeric value, or until it reaches the end of the string.
I don't know of a way to "turn off" or disable this behavior. (There may be a setting of sql_mode that changes this behavior, but likely that change will impact other SQL statements that are working, which may stop working if that change is made.
Typically, this kind of check of the arguments is done in the application.
But if you need to do this in the SELECT statement, one option would be cast/convert the column as a character string, and then do the comparison.
But that can have some significant performance consequences. If we do a cast or convert (or any function) on a column that's in a condition in the WHERE clause, MySQL will not be able to use a range scan operation on a suitable index. We're forcing MySQL to perform the cast/convert operation on every row in the table, and compare the result to the literal.
So, that's not the best pattern.
If I needed to perform a check like that within the SQL statement, I would do something like this:
WHERE t.memberid = '2001foo' + 0
AND CAST('2001foo' + 0 AS CHAR) = '2001foo'
The first line is doing the same thing as the current query. And that can take advantage of a suitable index.
The second condition is converting the same value to a numeric, then casting that back to character, and then comparing the result to the original. With the values shown here, it will evaluate to FALSE, and the query will not return any rows.
This will also not return a row if the string value has a leading space, ' 2001'. The second condition is going to evaluate as FALSE.
When comparing an INT to a 'string', the string is converted to a number.
Converting a string to a number takes as many of the leading characters as it can and still be a number. So '2001character' is treated as the number 2001.
If you want non-numeric characters in member_id, make it VARCHAR.
If you want only numeric ids, then reject '200.1character'

MySQL REPLACE string with regex

I have a table with about 50,000 records. One of the fields is a "imploaded" field consisting of variable number of parameters from 1 to 800. I need to replace all parameters to 0.
Example:
1 parameter 3.45 should become 0.00
2 parameters 2.27^11.03 should become 0.00^0.00
3 parameters 809.11^0.12^3334.25 should become 0.00^0.00^0.00
and so on.
Really I need to replace anything between ^ with 0.00 ( for 1 parameter it should be just 0.00 without ^).
Or I need somehow count number of ^, generate string like 0.00^0.00^0.00 ... and replace it. The only tool available is MySqlWorkbench.
I would appreciate any help.
There is no regex replace capability built in to MySQL.
You can, however, accomplish your purpose by doing what you suggested -- counting the number of ^ and crafting a string of replacement values, with this:
TRIM(TRAILING '^' FROM REPEAT('0.00^',(LENGTH(column) - LENGTH(REPLACE(column,'^','')) + 1)));
From inside to outside, we calculate the number of values by counting the number of delimiters, and adding 1 to that count. We count the delimiters by comparing the length of the original string, against the length of the same string with the delimiters stripped out using REPLACE(...,'^','') to replace every ^ with nothing.
The REPEAT() function builds a string by repeating a string expression n number of times.
This results in a spurious ^ at the end of the string, which we remove easily enough with TRIM(TRAILING '^' FROM ...).
SELECT t1.*, ... the expression above ... FROM table_name t1, from your table to verify the results of this logic (replacing column with the actual name of the column), then you can UPDATE table SET column = ... to modify the values. once you are confident in the logic.
Note, of course, that this is indicative of a problematic database design. Each column should contain a single atomic value, not a "list" of values, as this question seems to suggest.

match (row) against ('text') wont return results

$qstring = "SELECT titulo as value, id FROM blogs WHERE titulo LIKE '%".$term."%' LIMIT 5";
$qstring = "SELECT titulo as value, id FROM blogs WHERE MATCH(titulo) AGAINST ('.$term.') LIMIT 5";
The first one will return results but not really related to the query
the second will return:
Can't find FULLTEXT index matching the column list
why?
check value in $term that should be greater then 3 in case of FULLTEXT index search otherwise it will return null
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. The default minimum value is four characters. 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:
match() only works on field which have a FULLTEXT on them, exactly as the error message says. You'd have to do:
ALTER TABLE blogs ADD FULLTEXT INDEX tituolo_ft (titulo);
before you can use fulltext operations on the field.
As the error message implies, you can't use MATCH ... AGAINST unless there is a FULLTEXT index on the field you are comparing.
The LIKE statement should work though. I think the problem may be the double quotes in your pattern which are superfluous and will require corresponding quotes in the database value. Please show what database data you are trying to match.
In addition to the FULLTEXT index mentioned by others it looks like you are not properly quoting your text in the AGAINST clause. I think it should be:
AGAINST ('".$term."')
Or else, since you already have double quotes around your query just embed the variable:
AGAINST ('$term')