MySQL FullText search? - mysql

I am working on search functionality in my website. I want to provide a best search mechanism to users. I am using PHP/MYSQL.
Let's say user searched for "sport".
I have 30 records having word "sport" and 5 records having word "sports" but when I am searching for sport then following query only returns the result 30 who have the word "sport". But actually I think the best way to provide good search result is to display all the 30+5 records, all the records having sport or sports.
SELECT DISTINCT p.id, p.title, p.descr, p.tags FROM pdata p WHERE MATCH (p.title, p.tags, p.descr) AGAINST ('sport')
Please tell me some articles or some tips & tricks using which I'll be able to provide a good search functionality.

...MATCH (p.title, p.tags, p.descr) AGAINST ('sport*' IN BOOLEAN MODE)
May do the trick.
Edit, the MySQL documentation is an excellent resource for these kind of problems! :)

Just use the % wildcard on your search strings. This will allow any words formed by the search string to be matched. Sadly you will need to be in Boolean mode for this wildcard to work. Also all search strings must be greater then 3 characters in order to show up using full text search. this can be changed in the mysql system settings, but the default is 3.

In your case I would make the following query:
SELECT p.id, p.title, p.descr, p.tags
FROM pdata p WHERE (p.title LIKE
'%SPORT%' OR p.tags LIKE '%SPORT%' OR
p.descr LIKE'%SPORT%')
This query would find any articles which cover sportmagazines , summer-sports ect ect.

Related

Issue with Singular Words and MySQL Fulltext Searching

I've setup a fulltext search to listen on the title and description columns for my blog articles table in MySQL. The SQL that I use to search the table is as follows:
SELECT title,description,publish_date FROM table WHERE MATCH(title,description) AGAINST('cats','dogs') ORDER BY publish_date DESC LIMIT 100
This works (for 'dogs' and 'cats'), but when I use the singular ('dog' or 'cat') then I find no results. Not sure why this is going on, I've tried different variations like "+dog, +cat" and tried including IN BOOLEAN MODE as well ... Nothing works. And Yes I am sure that there are other words in the description column that are "dog" and "cat" as well as their plural versions.
How can I get singular words to work with MySQL?
The default minimum word length for full-text searches is 4 characters.
You'll need to change that in the server configuration. See here for some info on how to do it.
why don't you try something like this:
SELECT title,description,publish_date, MATCH(title,description) AGAINST('search') AS score FROM table WHERE MATCH(title,description) AGAINST('seacrh') ORDER BY score LIMIT 100;
maybe this will help but will not work propertly with one word

How to use prefix wildcards like '*abc' with match-against

I have the following query :
SELECT * FROM `user`
WHERE MATCH (user_login) AGAINST ('supriya*' IN BOOLEAN MODE)
Which outputs all the records starting with 'supriya'.
Now I want something that will find all the records ending with e.g. 'abc'.
I know that * cannot be preappended and it doesn't work either and I have searched a lot but couldn't find anything regarding this.
If I give query the string priya ..it should return all records ending with priya.
How do I do this?
Match doesn't work with starting wildcards, so matching with *abc* won't work. You will have to use LIKE to achieve this:
SELECT * FROM user WHERE user_login LIKE '%abc';
This will be very slow however.
If you really need to match for the ending of the string, and you have to do this often while the performance is killing you, a solution would be to create a separate column in which you reverse the strings, so you got:
user_login user_login_rev
xyzabc cbazyx
Then, instead of looking for '%abc', you can look for 'cba%' which is much faster if the column is indexed. And you can again use MATCH if you like to search for 'cba*'. You will just have to reverse the search string as well.
I believe the selection of FULL-TEXT Searching isn't relevant here. If you are interested in searching some fields based on wildcards like:
%word% ( word anywhere in the string)
word% ( starting with word)
%word ( ending with word)
best option is to use LIKE clause as GolezTrol has mentioned.
However, if you are interested in advanced/text based searching, FULL-TEXT search is the option.
Limitations with LIKE:
There are some limitations with this clause. Let suppose you use something like '%good' (anything ending with good). It may return irrelevant results like goods, goody.
So make sure you understand what you are doing and what is required.

Mysql full text search ignore repeated words take word at once

I need help in fulltext search in mysql.
I am looking for book named dreams. when i search for dreams i got
India in my dreams the greatest of all dreams vision
Dictionary of dreams - understanding dreams
Psyche on dreams & beyond dreams
Without dreams
Only dreams
Dreams
some other books
Actually i am looking for dreams
How to make 6th book to first one.
I want to ignore repeated words in this case dreams.
you can search here
I am facing these type of issues in different titles.
The relevance of columns with the search word repeated are the higest, The only solution I can see is to do a union query for exact matches with your standard full text search e.g:
SELECT * FROM books
WHERE title = 'Dreams'
UNION
SELECT * FROM books
WHERE MATCH(title) AGAINST("Dreams")
this will show the exact match first.
or you could
SELECT * FROM books
WHERE MATCH(title) AGAINST("Dreams")
ORDER BY (CASE WHEN title = 'Dreams' THEN 1 ELSE 0 END),.....
Do you want the exact case to be the first suggestion?
Try in order by:
"ORDER BY ('{$str_search}' = title) DESC"
This will make the exact case searchword you searched for appear first.
2 more solutions:
"ORDER BY ('{$str_search}' LIKE title) DESC"
"ORDER BY ('{$str_search}%' LIKE title) DESC"
3rd solution can be used to order up all that starts on your search word.
Note: This solution is pretty much the same as the CASE WHEN one.
Probably not relevant anymore, but if anyone comes looking I would reccommend using the levenshtein function on top to solve this. See below for more information and a full implementation in mysql
https://dba.stackexchange.com/questions/40450/mysql-full-text-search-increase-relevance-for-exact-matches
Levenshtein: MySQL + PHP
I can only suggest the usage of regular expressions :
http://dev.mysql.com/doc/refman/5.1/en/regexp.html

Against not returning score

There is something wrong with this query? This one works sometimes and sometimes not. For example with the word 'seven' it doesn't return any score, but i know that it appears on 29 rows at least in the body however it return as score 0.
With other words it work ok but not with this one. Anyone know why or have a different solution to sort it by relevance?
SELECT *,
( (MATCH(articles.name) AGAINST('seven'))*5 +
(MATCH(articles.subtitle) AGAINST('seven'))*3 +
(MATCH(articles.body) AGAINST('seven'))) AS search_score
FROM articles
LEFT JOIN matches ON articles.match=matches.id
ORDER BY search_score DESC
EDIT: I noticed that 'seven' is a stop word. There is other way to do this? stopwords
Add COALESCE(value,0) around each score.
Problem
If the word is too common, i.e. occurs in 50%+ of the rows, MySQL considers it a STOP-word and will not match against it.
Then there's the stop-word list (which you've already noticed)
See: http://dev.mysql.com/doc/refman/5.5/en/fulltext-stopwords.html
Solution
This answer: where to edit mysql fulltext stopword lists?
Tells you how to override/replace the default stop word list.
Here's the link to the MySQL docs page: http://dev.mysql.com/doc/refman/5.5/en/fulltext-fine-tuning.html

Use REGEXP in MySQL to match keywords for search engine in random order

I'm trying to use a regular expression to match a user entered search string to a title of an entry in my MySQL database.
For example I have the following rows in a table in my databse:
id title
1 IM2 - Article 3 Funky Business
2 IM2 - Article 4 There's no Business That's not Show Business
3 IM2 - There's no Business That's not Show Business
4 CO4 - Life's a business
When a user searches for "IM Article Business", the following query will be executed (spaces are replaced by "(.*)" using str_replace):
SELECT * FROM mytable WHERE title REGEXP 'IM(.*)Article(.*)Business'
This will return the first 2 rows.
Now, I want it to show the same results when a user uses the same words, but in another order, for example: "Business IM Article". The results MUST contain all words entered, only the order of how the words are entered shouldn't matter.
I couldn't figure out how to do it in any way and hoped regular expressions would be the answer. I've never used them before, so does anybody know how to do this?
Thanks,
Pascal
This isn't something regular expressions are great at. Fortunately, it's something SQL is pretty good at. (I'm going to not use mysql's regexp keyword, which I didn't even knew existed, and instead use the SQL standard "%" glob matching.)
select * from mytable where title like '%IM%' and title like '%Article%' and title like '%Business%'
Now title has to contain all three strings, but you haven't specified an order. Exactly what you want.