MySQL: How to do basic search by relevance? - mysql

I read the official page: http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html
but it's not providing an example
I have 1 col named "mycol", and suppose user input is "keyword1 keyword2". I want to display results ordered by relevance. I tried something like this:
select id,mycol,match(mycol) against('keyword1 keyword2' in boolean mode) as relevance from mytable
It's returning all records relevance is 0. What am I doing wrong?

try
select id,mycol,match(mycol) against('keyword1 keyword2') as relevance from mytable order by relevance desc

Related

query that returns rows that do not contain a word in MySql

I am trying to make a query where I select all the rows that do not contain a specific word, for this I have a fulltext type index in this column, try the following bolt works:
SELECT *
FROM products
WHERE MATCH(title) AGAINST(' -Dolo' IN BOOLEAN MODE)
So how can I perform this search?
If I have understood you correctly you want to find all the rows from the table that do not contain a word'Dolo'.
Well you can use NOT operator for that.
SELECT *
FROM products
WHERE NOT MATCH(title) AGAINST('Dolo');
Here is a DEMO.
Also, you can use it like this(because as the OP has asked: "if the whole word is "dolorem", would this query work?"):
SELECT title as Title
, MATCH(title) AGAINST('Dolo*' IN BOOLEAN MODE) as Score
FROM products
WHERE MATCH(title) AGAINST('Dolo*' IN BOOLEAN MODE) = 0;
* is a wildcard.
Other signs are described here: https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html
Here is the DEMO for the second example.

MySQL Full text search AND operator

Is it possible to use full test search in InnoDB engine with AND operator for natural language mode? I mean query like below but with all words as required:
SELECT *, MATCH (body) AGAINST ('mysql database') AS score FROM post ORDER BY score DESC;
For this query i want return all records which match both words:'mysql' AND 'database'. I know i can use + and BOOLEAN mode, but it causes another problems like other operators which i want to ignore (*,-,"'..)
Add a WHERE clause that tests for each word separately:
SELECT *, MATCH (body) AGAINST ('mysql database') AS score
FROM post
WHERE MATCH(body) AGAINST ('mysql') AND MATCH(body) AGAINST('database')
ORDER BY score DESC;

ORDER BY in MySql based on LIKE condition

I am facing difficulty in sorting the result based on field in mysql. Say for example I am searching the word "Terms" then I should get the results which starts with 'Terms' first and then 'Terms and' as next and then 'Terms and conditions' and so on.
Any one please help out who to fetch the search result based on my requirements in efficient manner using mysql query.
SELECT * FROM your_table WHERE your_column LIKE "Terms%" ORDER BY your_column;
Based on the storage engine and mysql version you probably can use the full text search capabilities of MySQL. For example:
SELECT *, MATCH (your_column) AGAINST ('Terms' IN BOOLEAN MODE) AS relevance
FROM your_table
WHERE MATCH (your_column) AGAINST ('Terms' IN BOOLEAN MODE)
ORDER BY relevance
You can find more info here: http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html
Or if you don't want FTS another possible solution where ordering is strictly based on the length (difference) of the strings.
SELECT * FROM your_table WHERE your_column LIKE "Terms%" ORDER BY ABS(LENGTH(your_column) - LENGTH('Terms'));
You are looking for fulltext search. Below a very simple example
SELECT id,name MATCH (name) AGAINST ('string' > 'string*' IN BOOLEAN MODE) AS score
FROM tablename WHERE MATCH (name) AGAINST ('string' > 'string*' IN BOOLEAN MODE)
ORDER BY score DESC
The advantage of this is that you can control the value of words. This is very basic, you can 'up' some matches or words (or 'down' them)
In my example an exact match ('string') would get a higher score than the string with something attached ('string*'). The following line is even one step broader:
'string' > 'string*' > '*string*'
This documentation about fulltextsearch explains allot. It's a long read, but worth it and complete.
Don't use fulltext index if you search for prefix string!
Using LIKE "Term%" the optimizer will be able to use a potential index on your_column:
SELECT * FROM your_table
WHERE your_column LIKE "Terms%"
ORDER BY CHAR_LENGTH(your_column),your_column
Note the ORDER BY clause: it first sorts by string length, and only use alphabetcal order to sort strings of equal length.
And please, use CHAR_LENGTH and not LENGTH as the first count the number of characters, whereas the later count number of bytes. Using a variable length encoding such as utf8, this would made a difference.

mysql match against multiple words

Below is an example sql I am stuck with, it will not return a product named "iphone 4s", It returns 10 other result. Any help would be great thanks
1st sql example
SELECT * FROM products
WHERE match(desc) against('+iphone +4s' IN BOOLEAN MODE) LIMIT 10";
result: contains the words 'iphone' and '4s'
2nd sql example
SELECT * FROM products
WHERE match(desc) against('+iphone 4s' IN BOOLEAN MODE) LIMIT 10";
result: contains the words 'iphone', but rank rows higher if they also contain '4s'
3rd sql example
SELECT * FROM products
WHERE match(desc) against('iphone 4s' IN BOOLEAN MODE) LIMIT 10";
result: contains the words 'iphone' or '4s'
What I want to search is 'iphone 4s', but it comes with other result, like 'iphone is good, but 4s...', 'new iphone 5 has published...',...
Can anyone help me to solve it? thanks.
To match an exact phrase, just use double quotes to surround the phrase to match;
SELECT *
FROM products
WHERE MATCH(desc)
AGAINST('"iphone 4s"' IN BOOLEAN MODE)
LIMIT 10
More info at the manual pages.
Use REGEXP
SELECT * FROM products
WHERE desc REGEXP 'iphone[[. .]]*4s'
LIMIT 10;
SQLFiddle demo

mysql multiple OR NOT LIKES

I have a wordpress plugin that essentially creates a mysql query and returns the results to wordpress.
It is user driven and so can end up in large queries with multiple NOT LIKEs which results in a very slow query.
Any suggestions that I could use to improve:
SELECT field1,field2,field3,field4
from datatable
WHERE (title NOT LIKE '%word%' AND title NOT LIKE '%word2%'
AND title NOT LIKE '%word3%' AND title NOT LIKE '%word4%'
AND title NOT LIKE '%word5%' AND title NOT LIKE '%word6%'
AND title NOT LIKE '%word7%' AND title NOT LIKE '%word8%'
AND title NOT LIKE '%word9%')
AND MATCH (title) AGAINST ("\"brandname\" " IN BOOLEAN MODE)
ORDER BY total ASC LIMIT 0,60
The customer is adding a lot of negative keywords to the wordpress plugin which results in larger queries than the one above.
This is most easily done with REGEXP. For multiple words, use a group like (one|two|three)
SELECT
field1,
field2,
field3,
field4
from datatable
WHERE
title NOT REGEXP '(word1|word2|word3|word4|word5...|word9)'
AND MATCH (title) AGAINST ("\"brandname\" " IN BOOLEAN MODE)
ORDER BY total ASC
LIMIT 0,60
You can use a REGEXP operation to compare all the patterns at once.
Your query will be something like:
SELECT field1,field2,field3,field4
FROM data table
WHERE title NOT REGEXP '^word[0-9]?$'
AND MATCH(title) ("\"brandname\" " IN BOOLEAN MODE)
ORDER BY total ASC LIMIT 0,60