How to not search for exact word match using LIKE? - php

Hello guys I am using the following query to select data
mysql_query("SELECT * FROM prodcuts WHERE prod_name LIKE '%".$search."%'");
The problem is when you search let's say 'he' it select more than I would like. It takes 'hello' 'helblabla' everything with 'he' in it.
What I would like to do is when let's say you are searching for playstation it accepts the following searches playstatioq, yplaystation, playstationq etc..
So I want to allow the search to differ one letter from the exact product name. Any ideas how this can be done?
Thanks in advance

Sounds like what you want is the Levenshtein distance. Check out MySQL Levenshtein here on StackOverflow for more information.

Expanding on what Glen Solsberry wrote, you can use an '_' (underscore) for a single letter wild card search. For example:
"SELECT * FROM prodcuts WHERE prod_name LIKE '%_".$search."_%'"
If your $search var is 'laystatio', this query will match 'playstation', 'yplaystation', 'playstationq' and 'playstatioq'.
If your $search var is 'playstation', or 'playstatioq', or 'yplaystation', using soundex, this next query should return the result you are after, plus a heap that are a close match:
"SELECT * FROM prodcuts WHERE SOUNDEX(prod_name) LIKE SOUNDEX('".$search."')"

You could potentially solve your problem obliquely by building an index with something like Elastic Search or Solr that provides fuzzy matching for full text queries.
Depending on the scale of your problem, efficiency requirements, and how fuzzy you need your matches to be, it could save you a lot of effort. On the other hand, it could of course be overkill.

Related

PHP search function, for searching DB with non exact search term [duplicate]

I have a table dictionary which contains a list of words Like:
ID|word
---------
1|hello
2|google
3|similar
...
so i want if somebody writes a text like
"helo iam looking for simlar engines for gogle".
Now I want to check every word if it exists in the database, if not it should
get me the similar word for the word. For example: helo = hello, simlar = similar, gogle = google.
Well, i want to fix the spelling errors. In my database i have a full dictionary of all english words. I coudn't find any mysql function which helps me. LIKE isn't helpfull in my situation.
you can use soundex() function for comparing phonetically
your query should be something like:
select * from table where soundex(word) like soundex('helo');
and this will return you the hello row
There is a function that does roughly want you want, but it's intensive and will slow queries down. You might be able to use in your circumstances, I have used it before. It's called Levenshtein. You can get it here How to add levenshtein function in mysql?
What you want to do is called a fuzzy search. You could use the SOUNDEX function in MySQL, documented here:
http://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_soundex
You query would look like:
SELECT * FROM dictionary where SOUNDEX(word) = SOUNDEX(:yourSearchTerm)
... where your search term is bound to the :yourSearchTerm parameter value.
A next step would be to try implementing and making use of a Levenshtein function in MySQL. One is described here:
http://www.artfulsoftware.com/infotree/qrytip.php?id=552
The Levenshtein distance between two strings is the minimum number of
operations needed to transform one string into the other, where an
operation may be insertion, deletion or substitution of one character.
You might also consider looking into databases that are aimed at full text searching, such as Elastic Search, which provides this natively:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html

Searching for a term using SQL MATCH which includes spaces

This may be a newbie question, as I'm not an expert in SQL. However, couldn't find the answer using Google.
I have a table called record_fields which contains the majority of my system's content, which I want to search in. The content cell is defined as LONGTEXT as it can include extremely long input.
Originally, I used (simplifying the query a bit for clarity sake):
SELECT * FROM record_fields WHERE LOWER(content) LIKE LOWER('%{$keyword}%')
Execution time aside, this query has one major issue. If I search for the term "post" it will return all content which has words like "poster", "posting" and others. I wanted to add a FULLTEXT search.
Now the query looks like this (again, simplified):
SELECT * FROM record_fields WHERE MATCH (content) AGAINST ('{$keyword}')
However, this is still problematic. With MATCH, if my system's users search for the words "Bank of America", for example, all records that either have the word "Bank" and "America" will be returned.
TL;DR - my question is this:
how do I use MATCH to search for exact phrases with space in them?
Any help would be highly appreciated, thanks in advance!
%{keyword}% matches all text sub-strings that include your keyword anywhere in the string. MATCH usually takes all keywords in the match string as individual search terms, and matches against each. You can use boolean mode and use a + symbol before each required keyword. Take a look at the MySQL reference for this.
Edited the answer to reflect Idan's response in not getting the results from the suggested %keyword solution.
You can use Match Against With Boolean Mode and you can put your input string inside '"{$keyword}"'.
Check last example in below link
https://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html
SELECT * FROM record_fields WHERE MATCH (content) AGAINST ('"{$keyword}"' IN BOOLEAN MODE )

How MySQL does the fulltext search if I need to find two words that are not close each other

If I am using MySQL fulltext search to find term " ford fiesta ", and I am searching from the field that looks like this: "cars ford engines fiesta".
Is MySQL going to give me a result ? I do not want it to only find " ford fiesta " if these words are next to each other in the field that I am searching from, for example " cars ford fiesta engines ".
If MySQL is not going to give me a result by default, can I configure it to do so ( to match words if they are appearing anywhere in the text that I am searching from ), or is there any other way to achieve this ?
Thanks
Use REGEXP:
SELECT * FROM `table` where `field` REGEXP 'ford.*fiesta' = 1
It will return those records whose field field contains string that has words ford and fiesta with any string between them. REGEXP returns 1 on match and 0 if not matched.
Use like and then add wildcard parameters.
as such
SELECT * FROM table WHERE field LIKE '%ford fiesta%'
Maybe completely unrelated, but when I started to create a bit more complex search engines I started using a special Database for it.
Take a look at elasticSearch, once you get it up and running it is crazy simple to specify needs like yours.
Specially the query_string from ElasticSearch would fit your needs. You can even specify what fields you want to run the query on.
As I said, once you want to get over from a simple search to advanced search, MYSQL ain't the right one to do the job.
Cheers

Autocomplete SQL Query suggestions (Ajax+PHP)

I have a question regarding SQL best practices when formulating a query for use in an Autocomplete form (jquery Axax + PHP).
Let us assume the following:
I have a database with the titles of books
Some books have titles without a definite article ("The" or "A") such as "Life of Pi"
Some books have titles with a definite article ("The" or "A") such as "The Catcher in the Rye"
As a result, users will input the title of the book either using "The" at the beginning or simply omitting the "The" and start the query without any definite article.
Three possible queries seem to exist:
SELECT 'title' FROM 'books' WHERE 'title' LIKE '%$string'
or
SELECT 'title' FROM 'books' WHERE 'title' LIKE '$string%'
or
SELECT 'title' FROM 'books' WHERE 'title' LIKE '%$string%'
When using the first query method (where the % is before the string), it is difficult to get any results, since the wildcard before the string seems to behave erroneously.
When using the second query, it seems to favor exact matches using "The" before a title. Thus, a user searching for "The Catcher in the Rye" will find the book, but a user searching for "Catcher in the Rye" will not.
The last result is the best one, since it has a wildcard before and after the string. However, it also gives the longest auto-complete list. The user will have to type a few letters to narrow down the search result.
Any ideas on implementing a more efficient query? Or is the third option the best one (seeing as it is not feasible to separate the definite article in the title of a book?
Thanks in advance,
You can do a search using Regular Expressions (query result comes quickly)
and do not forget to add limitation to your results.
a small example
SELECT title FROM books WHERE title REGEXP '$string' LIMIT 20
or you can use word boundaries
SELECT title FROM books WHERE title REGEXP '[[:<:]]$string[[:>:]]' LIMIT 20
see the documents http://dev.mysql.com/doc/refman/5.5/en/regexp.html
$query = mysqi_query("SELECT title FROM books WHERE title REGEXP '$string'");
if($query->num_rows() == 0) {
//First remove all the stop words like for, the, of, a from the search string.
$stopWords = array('/\bfor\b/i', '/\bthe\b/i', '/\bto\b/i', '/\bof\b/i','/\ba\b/i');
$string = preg_replace($stopWords, "", $string);
//Then, use
mysqli_query("SELECT title FROM books WHERE title REGEXP '$string'");
}
I would suggest using the third method with wildcards on either side of the string. If you are worried about the size of the returned result set, perhaps limit the results to a certain number, and as the user types the list will naturally get smaller and more specific.
you may also consider allowing searches for 'Catcher Rye' that should still match.
in this case - you would tokenize each word in the title as well as the words entered by the user and find the best matches.
otherwise only autocomplete after say 4 or more characters have been entered, and use option 3.
If you're worried about the quantity of suggestions, can you modify the change event to only retrieve suggestions after they have typed some minimum number of characters in the field?

measure relevance of a search term returned matched against results

Is there a PHP or MySQL function which will check how relevant a matching field is? Could it review the string and match against a percentage of characters?
For example I am doing a basic search script pulling back results but how can I make the more relevant results appear at the top?
A lot depends on your data and the type of searches that you are expecting. But basically, you could be looking for a fuzzy search. Soundex and Levenshtein distance are two of the many functions that you can use for string matches
http://php.net/manual/en/function.levenshtein.php
Well, you are asking a few complicated questions here. Mostly, I think you are looking for information retrieval techniques. Some answers are all over Stack OVerflow.
What tried and true algorithms for suggesting related articles are out there? is great I think
You might want to use the levenshtein distance if you are just looking for how closely a keyword matches an existing keyword.
I tried :P
Mysql has a function MATCH
You can youse it like
SELECT * FROM `table` WHERE MATCH(content) AGAINST('search text')
So it will look within content how relevancy it is.
But you need to index field content to FULLTEXT which requires an table type "MYISAM".
The output will automaticly sorted ascending.
hope this helps

Categories