MySQL full text search on JSON data - mysql

I'm trying to replicate the following LIKE query using a full text search on JSON data;
SELECT * FROM table
WHERE response LIKE '%"prod_id": "foo"%'
AND response LIKE '%"start_date": "2016-07-13"%'
In my database the above query returns 28 rows
This is my attempt:
SELECT * FROM table
WHERE MATCH(response)
AGAINST('+"\"prod_id\": \"foo\"",+"\"start_date\": \"2016-07-13\""')
However this returns over 4,500 rows (the same as running the first query for only the prod_id ~1,900 rows when running the first query on just the date)
It was my understanding that +"text here" would indicate a required word, and that literal double quotes (present in the JSON data) should be escaped, and that , would indicate a split between the two strings I'm looking for. What am I not understanding correctly? Is there any point in running this as a full text query anyway?

Thanks to #Sevle I've tweaked my query like so, and it's returning the correct results;
SELECT * FROM table
WHERE MATCH(response)
AGAINST('+\"prod_id: foo\" +\"start_date: 2016-07-13\"' IN BOOLEAN MODE)
The comma was not helping and I was escaping the wrong characters, and of course I did need IN BOOLEAN MODE to be added. Finally, I removed the double quotes I was searching for in the JSON string.
It may also be worth noting that as I'm using PHP PDO to run this query I also had to make the following tweaks.
Instead of constructing the query like so trying to bind the variables like I normally would;
$query = $db->prepare('...AGAINST('+\"prod_id: :prod_id\" +\"start_date: :start_date\"');
$query->execute(array('prod_id' => 'foo', 'start_date' => '2016-07-13'));
I had to do this, as I found I could not bind variables in full text searches
$sql_against = $db->quote('...AGAINST('+\"prod_id: foo\" +\"start_date: 2016-07-13\"');
$query = $db->prepare("...AGAINST($sql_against IN BOOLEAN MODE)")

Related

MySQL Query Using JSON_CONTAINS

I have a MySQL 5.7 table which includes a column of type VARCHAR named 'area' which contains JSON data. For example
["BS20","BS21"]
I need to search on that table to find the first row containing a particular string. The string is contained in a variable like
$area = BS20;
and I have tried this for my query
SELECT * FROM aedv2_admin WHERE JSON_CONTAINS(area,'$area')=1
and I get an error
Invalid JSON text in argument 2 to function json_contains: "Invalid value." at position 0.12
For testing I have tried hard coding argument 2 as BS20 and 'BS20' but neither helps. What am I doing wrong?
Phew! That was a bit painful, but with thanks to Akina my final code ended up like this
$area = '\"'.$_POST['area'].'\"';
$query_sponsor = "SELECT * FROM aedv2_admin WHERE JSON_CONTAINS(area,'$area')";

MYSQL REGEXP with JSON array

I have an JSON string stored in the database and I need to SQL COUNT based on the WHERE condition that is in the JSON string. I need it to work on the MYSQL 5.5.
The only solution that I found and could work is to use the REGEXP function in the SQL query.
Here is my JSON string stored in the custom_data column:
{"language_display":["1","2","3"],"quantity":1500,"meta_display:":["1","2","3"]}
https://regex101.com/r/G8gfzj/1
I now need to create a SQL sentence:
SELECT COUNT(..) WHERE custom_data REGEXP '[HELP_HERE]'
The condition that I look for is that the language_display has to be either 1, 2 or 3... or whatever value I will define when I create the SQL sentence.
So far I came here with the REGEX expression, but it does not work:
(?:\"language_display\":\[(?:"1")\])
Where 1 is replaced with the value that I look for. I could in general look also for "1" (with quotes), but it will also be found in the meta_display array, that will have different values.
I am not good with REGEX! Any suggestions?
I used the following regex to get matches on your test string
\"language_display\":\[(:?\"[0-9]\"\,)*?\"3\"(:?\,\"[0-9]\")*?\]
https://regex101.com/ is a free online regex tester, it seems to work great. Start small and work big.
Sorry it doesn't work for you. It must be failing on the non greedy '*?' perhaps try without the '?'
Have a look at how to serialize this data, with an eye to serializing the language display fields.
How to store a list in a column of a database table
Even if you were to get your idea working it will be slow as fvck. Better off to process through each row once and generate something more easily searched via sql. Even a field containing the comma separated list would be better.

How to escape a whole sql string instead of escaping each argument?

I use https://github.com/mysqljs/mysql.git library.
I have a mysql db query architecture in which I can not modify the SQL query file one by one to escape each argument for there are too many files, but all the SQL queries will call the query method of a same base mysql instance, so I wonder if I can escape the eventual SQL string in the base mysql query method.
I want to escape the whole SQL string like
select * from tableA where name = 'foo'bar
to
select * from tableA where name = 'foo\'bar'
with some function like mysql_escape("select * from tableA where name = 'foo'bar'") instead of doing this using preparing queries or concating escaped strings.
There isn't a way to do this that wont result in a really inefficient function or some bad hack. Just use parameterized queries, Its basically what they are there for. If you cant use those you use concat strings.
Running mysql_escape on a whole query will require the function to know what characters are part of your query and what characters are part of the input values. You could write some kind of stupid regex to try pull the values from the query and then escape them but its just a bad idea.

A couple of basic Sql Profiler questions

(Sorry for the longish question, I'll try to be concise.)
I'm running SQL Server Profiler and I'm chasing down some performance issues. I'm relatively new to what the profiler does and I've exported the traces into a table so I can run queries against the data.
One thing I've been running up against is some seemingly odd behavior doing select queries against the TextData field of the table generated by the trace export. It may have to do with the field's data type (ntext, null). I'm selecting for particular values, but getting unexpected results. For example, if I do this:
select * from [TraceAnalyzer].dbo.TraceTable
and I'm interested in values like this:
exec [Sproc_of_interest] #parm1=992
I'd do a query like this:
select * from [TraceAnalyzer].dbo.TraceTable
where TextData like '%exec [Sproc_of_interest] #parm1=%'
but the return result is empty.
Also, if I do a query like:
select * from [TraceAnalyzer].dbo.TraceTable
where TextData like '%exec [Sproc_of_interest]%'
I get unexpected TextData values like exec sp_reset_connection
Would the square brackets in the criteria be messing things up? I've tried omitting them, but that just excludes everything. I'm not aware of escape characters in SQL select queries, but when I copy/paste the value from one of the offending records, the pasted value does not appear to contain anything that would meet the original query's criteria.
Any insights would be greatly appreciated. Thanks.
[Sproc_of_interest] in the pattern syntax is interpreted as matching one character that is in the set S,p,r,o,c,_,o,f,_,i,n,t,e,r,e,s,t.
Three possible ways of solving this are below.
1) Escape [ with square brackets
LIKE '%exec [[]Sproc_of_interest] #parm1=%'
2) Use an escape character
LIKE 'exec \[Sproc_of_interest] #parm1=' ESCAPE '\'
3) Use CHARINDEX instead of escaping anything
WHERE CHARINDEX('exec [Sproc_of_interest] #parm1=' , TextData) > 0

How to do a correct query in mysql with in the string \40

I have this string: alexandre.aba\40gmail.com#gtalk.ofelia.dcc.fc.up.pt stored as JabberID in USER table in my database.
The problem is when i execute this query:
SELECT * FROM `USER` WHERE JabberID='alexandre.aba\40gmail.com#gtalk.ofelia.dcc.fc.up.pt'
It returns:
MySQL returned an empty result set (i.e. zero rows).
I think it's the \40 that is causing the problem but i don't know how to fix it.
You should think about using prepared statements instead since it's safer but to correct the current string look at the link http://dev.mysql.com/doc/refman/5.1/en/string-literals.html for a list of special characters.
I think the \ should be replaced with \\