Advanced search term in php and MySql - php

I have a MySql table contain a title field.
Suppose a user enter a term in an input textbox.
Now I want to select rows whose title field has one of the following states:
1) its title is exactly the same as term : "sugar">>"sugar"
2) one of the words of its title is like the term : "pretty flower" >> "rose flower"
3) its title is from the same Word family as that term (term is root word of those) : "biology" >> "biography, biodegradable, symbiotic"
I'm using laravel. if can suggest any solution for that , Would be great

This was an easy solution until you mentioned word family...
However, this is something that is still achievable. It's about how you approach it.
You'll start by using the like condition in MySQL.
You can read more about it on the MySQL Website relating to Pattern Matching
Here's an example of that:
SELECT * FROM my_table WHERE field1 LIKE '%searchTerm%';
In terms of getting results by "word family", you may want to consider adding tags to the result.
Add a tags field in the table and add an array of tags that would relate to the "word family".
Your query would then look something like this:
SELECT * FROM my_table WHERE field1 LIKE '%searchTerm%' OR field2 LIKE '%searchTerm%';
You'll need to loop through the array of tags to find what matches, if at all.
Just my approach to get started.
In terms of how to do this is Laravel, your query may look something like this, according to their documentation
$results = DB::table('table1')
->where('myfield', 'like', '%searchterm%')
->get();
I surely hope this puts you in the right direction.

Related

Querying a table where the field contains any order of given text strings

I want to query a table as follows:
I have a field called "category" and my input match contains N separate words. I want the query to match all rows that contain all N words, but in any order.
For example if the field category contains "hello good morning world", my input query can contain "hello morning" or "good" or "world hello" and all are matches to the query.
How do I formulate such an SQL expression?
Also it would be good if the query can be made case insensitive.
If you are using MySQL you can use the boolean fulltext search feature to achieve this. You can put a + in front of each term and then only results with all the terms, in any order, will be returned. You will need to make sure the column containing the category field has a fulltext index specified on it for this to work. Other database engines probably have similar features. So for example you might do something like the following assuming there were a fulltext index over the category column...
SELECT * FROM myTable WHERE MATCH (category) AGAINST ('+term1 +term2 +term3' IN BOOLEAN MODE);
I would avoid using the "LIKE" operator as others have suggested you would have to worry about the headache of mixed upper/lower case and if you have a large database using a % in the front of a LIKE search term is going to cause a full table scan instead of using an index which is horrible for performance.
I'm not writing the loop that will build this query for you. This will get the job done, but it will be pretty inefficient.
SELECT * FROM table
WHERE (
TOUPPER(category) LIKE '*HELLO*' AND
TOUPPER(category) LIKE '*GOOD*' AND
TOUPPER(category) LIKE '*MORNING*' AND
TOUPPER(category) LIKE '*WORLD*'
);
You could also research using REGEXes with SQL.

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?

MySQL PHP match words in query with database column

I have the following structure of a table [id - title - tag - ..]
I want to achieve the following:
If there is a record in table with title "I love my job and it is my hobby"
If a query is submitted having two words from the sentence then this sentence should be selected. E.g. query "love hobby". It should give me the above title and not for example "I love my job". At least the sentence with more words matching the query keywords first then the less ones later.
how can I do this search on the title column of my table?
I apologize if explanation not clear...more than happy to help clarify.
Thank you all
Try this :
SELECT title FROM your_table WHERE title LIKE '%love%' AND title LIKE
'%hobby%'
Look into mysql's built in full text search capabilities. In boolean mode, you could transform your query to +love +hobby and have results returned without full table scans. Be aware that this only works with myisam tables, might want to move the indexed data out of the main tables since myisam doesn't support things like foreign keys or transactions.
For more advanced free text indexing you could try sphinx (have mysql look-and-feel interface too) or solr.
If you're using MyISAM or innoDB, you can use the MySQL fulltext search:
SELECT * FROM table_name WHERE MATCH (title) AGAINST ('love hobby' IN BOOLEAN MODE);
It'll also search for individual words as well.
Read this: https://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html
You can also use MySQL REGEXP
SELECT title FROM table WHERE title REGEXP ' love .+ hobby';
If you have it as a single string then try:
SELECT title FROM table WHERE title REGEXP REPLACE('love hobby', ' ', '.+ ');

Trying to do a php/mysql search and need to break string into array and search

My users put search terms in an input field. The script I'm using stores that in a $find variable. It then searches mysql like so:
"select * from mytable WHERE title LIKE '%$find%' or description LIKE '%$find%'";
I want to be able to pull a result, even if 1 word is in the title and another in the description, which currently doesn't happen. So.. I'm guessing I need to break the $find variable into an array with a function. After that, how would I do the search in mysql? Since I never know how many words will be in the search (they might decide to search for 8 words at once), how do I reference the array in the mysql query?
Thx in advance!
You should use a FULLTEXT index and build a proper boolean search query on it.
You MAY achieve the effect you want without it, but this would be very slow compared to using FULLTEXT index. You would have to use explode to get the list of words, then build a WHERE condition like concat(title, description) LIKE '%word1%' AND concat(title, description) LIKE '%word2%' etc.
(In my first answer I stated that achieving this effect is impossible without FULLTEXT. I was wrong and edited this answer.)

MySQL - Filter result

I want to filter result of my SQL query. I want to select everything that has some specific text in some column.
Example:
SELECT * FROM categories WHERE (name
has 'abc' values in it's value ex.
MyabcCategory)
Also maybe it is not very good idea to do that in query, maybe it is better to get all and then filter array instead? But I don't know how to do that aether.
Use LIKE with % wildcard:
SELECT * FROM categories WHERE name LIKE '%abc%'
This will give you all the records that have abc somewhere in them.
You can learn more about it here :)
You want to use the LIKE operator, with % to match any character before and after your specific word :
select *
from categories
where name like '%abc%';
But note that doing so, MySQL will scan each line of the table, every time the query is executed... which might not be great if you have a lot of data.
If you're searching for some kind of text, you might either want to :
Use a FULLTEXT index, if you're working with MyISAM tables.
Or, use a solution that's separated from MySQL, with a specific indexing/search engine, such as Solr.
SELECT * FROM categories WHERE name LIKE '%abc%'

Categories