I have a search engine that searches addresses. It works as designed but I've run across an issue that I can't figure out a work around for.
Currently if I search for "23 Main St" and let's say Main street is in the 87232 zip code. This search will display every address that's on Main street because the street number I'm searching for has "23" with is also in the 87232 zip code.
I'm wondering if there is a way to program it to accept the space behind the "23 " and that would rule out the zip code? Or maybe you guys have a more thought out solution?
Here is my query code. It uses ajax live search:
if($_POST['query'] != '') {
$pieces = explode(" ", $_POST['query']);
$index = 0;
$substring = "";
while ($index < count($pieces)) {
$substring .=" CONCAT(Name,Address,City,State,Zip) like '%" . $pieces[$index] . "%'" ;
if ($index !=count($pieces)-1){
$substring .= " and ";
}
$index++;
}
$query = "SELECT * FROM database where ";
$query .= $substring;
$query .= ' ORDER BY Name ASC, dt DESC ';
}
I create a simple search form. Firstly I explode words and make some query (for search multiple words at once). Also, I want to search only in Movie titles. Movie titles can be found in movie_data.
My database called movies have rows:
id and
movie_data - contains movie data in JSON. Example storaged data in json:
{"movie_title":"Forrest Gump","movie_cover":"http://1.fwcdn.pl/po/09/98/998/7314731.6.jpg","movie_name_en":"","movie_desc":"Historia życia Forresta, chłopca o niskim ilorazie inteligencji z niedowładem kończyn, który staje się miliarderem i bohaterem wojny w Wietnamie.","movie_year":"1994","movie_genres":"DramatKomedia"}
Here is my code. This code don't return any results.
$query = 'Forrest Gump';
$words = explode(' ', $query);
$i = 0;
$len = count($words);
$query_build = '';
foreach ($words as $item) {
if ($i == $len - 1) {
$query_build .= ' titlemov LIKE "%$item%"';
} else {
$query_build .= ' titlemov LIKE "%$item%" OR ';
}
// …
$i++;
}
$sql = "SELECT movie_data, JSON_EXTRACT(movie_data, '$.movie_title') AS titlemov
FROM movies WHERE $query_build";
This code don't result any items
UPDATE
I updated my code.
$query = 'Forrest Gump';
$words = explode(' ', $query);
$i = 0;
$len = count($words);
$query_build = '';
foreach ($words as $item) {
if ($i == $len - 1) {
$query_build .= " JSON_EXTRACT(movie_data, \'$.movie_title\') LIKE '%$item%'";
} else {
$query_build .= " JSON_EXTRACT(movie_data, \'$.movie_title\') LIKE '%$item%' OR ";
}
// …
$i++;
}
$sql = "SELECT * FROM movies WHERE $query_build";
Now i getting error:
Warning: mysqli::query(): (22032/3141): Invalid JSON text in argument 1 to function json_extract: "Missing a comma or '}' after an object member." at position 228. in /search.php on line 43
Line 43:
$result = $conn->query($sql);
var_dump of $sql var:
SELECT * FROM movies WHERE JSON_EXTRACT(movie_data, '$.movie_title') LIKE '%Forrest%' OR JSON_EXTRACT(movie_data, '$.movie_title') LIKE '%Gump%'
Hmm?
titlemov doesn't exist for your where clause to use. What you want to use inside your where clause (specified in the $query_build) is the JSON_SEARCH function. Here's what it looks like in general with wildcards for the movie name:
SELECT movie_data, movie_data->'$.movie_title' AS titlemov FROM movies
WHERE JSON_SEARCH(movie_data->'$.movie_title', 'one', "%orrest Gum%") IS NOT NULL;
You'll just need to modify your $query_build string. I also drop the needless JSON_EXTRACT function calls.
Try this:
$query_build = " JSON_SEARCH(movie_data->'$.movie_title', 'one', '%$item%') IS NOT NULL";
Final note, I'm assuming $item is not a user supplied string, otherwise this opens you up to SQL injection. If it is supplied by user, you'll want to use a prepared statement and bind this value.
I have concatenated three tables to one table that is edit all. Now i'm going to retrieve the all the 4 values that starts with the particular letter, But is displaying all values with starts with different letter.
include "config.php";
$term = strip_tags(substr($_POST['searchit'],0,100));
$term = mysql_real_escape_string($term);
if($term=="")
echo "Enter Something to search";
else{
$query = mysql_query("select distinct videoname,category,name,email from edit_all
where videoname like '$term%' or category like '$term%' or name like '$term%' or email like '$term%'limit 1") or die(mysql_error());
$string= '';
if (mysql_num_rows($query))
{
while($row = mysql_fetch_assoc($query)){
$string .= "<b><a href='#'>".$row['videoname']."</a></b> -<br> ";
$string .= $row['category']."-<br>";
$string .= $row['name']."-<br>";
$string .= $row['email']."-<br>";
$string .= "\n";
}
}
else{
$string = "No matches found!";
}
echo $string;
}
?>
I am building a simple live search based on this tutorial: http://blog.ninetofive.me/blog/build-a-live-search-with-ajax-php-and-mysql/
It works fine for queries like this with one word:
Or for queries with part of a word:
Or for queries with two words or parts of words where they occur together in the results being searched:
But if I search for two words that do not occur next to each other the query fails:
How would I modify my query so that I can search for any number of keywords that appear at any location in my results?
For example if my db has a record such as: The quick brown fox jumps over the lazy dog
I want a result to be returned if I search for: quick jumps dog or dog over not just quick brown or fox jumps or fox and so on.
I was thinking something along the lines of exploding my query if it has more than one word in it and then making my $search_string into an array of keywords for MySQL to query but I don't know if that is the best way to go about it.
Query:
// Get Search
$search_string = preg_replace("/[^A-Za-z0-9]+[.]/", " ", $_POST['query']);
$search_string = $tutorial_db->real_escape_string($search_string);
// Check Length More Than One Character
if (strlen($search_string) >= 1 && $search_string !== ' ') {
// Build Query
$query = 'SELECT * FROM search WHERE subsection LIKE "%'.$search_string.'%" OR def LIKE "%'.$search_string.'%" OR exception LIKE "%'.$search_string.'%" ORDER BY subsection ASC';
Full code:
<?php
/************************************************
The Search PHP File
************************************************/
/************************************************
MySQL Connect
************************************************/
// Credentials
$dbhost = "localhost";
$dbname = "livesearch";
$dbuser = "live";
$dbpass = "search";
// Connection
global $tutorial_db;
$tutorial_db = new mysqli();
$tutorial_db->connect($dbhost, $dbuser, $dbpass, $dbname);
$tutorial_db->set_charset("utf8");
// Check Connection
if ($tutorial_db->connect_errno) {
printf("Connect failed: %s\n", $tutorial_db->connect_error);
exit();
}
/************************************************
Search Functionality
************************************************/
// Define Output HTML Formating
$html = '';
$html .= '<li class="result">';
$html .= '<a target="_blank" href="urlString">';
$html .= '<h2><b> codeString - yearString - chapterString - sectionString - SUBHERE</b></h1>';
$html .= '<h3>defString</h3>';
//try to add exception string
$html .= '</br><h3>exceptionString</h3>';
$html .= '</a>';
$html .= '</li>';
// Get Search
$search_string = preg_replace("/[^A-Za-z0-9]+[.]/", " ", $_POST['query']);
$search_string = $tutorial_db->real_escape_string($search_string);
// Check Length More Than One Character
if (strlen($search_string) >= 1 && $search_string !== ' ') {
// Build Query
//$query = 'SELECT * FROM search WHERE function LIKE "%'.$search_string.'%" OR name LIKE "%'.$search_string.'%"';
$query = 'SELECT * FROM search WHERE subsection LIKE "%'.$search_string.'%" OR def LIKE "%'.$search_string.'%" OR exception LIKE "%'.$search_string.'%" ORDER BY subsection ASC';
// Do Search
$result = $tutorial_db->query($query);
while($results = $result->fetch_array()) {
$result_array[] = $results;
}
// Check If We Have Results
if (isset($result_array)) {
foreach ($result_array as $result) {
// Format Output Strings And Hightlight Matches
//$display_function = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['function']);
//$display_name = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['name']);
//$display_url = 'http://php.net/manual-lookup.php?pattern='.urlencode($result['function']).'&lang=en';
// Format Output Strings And Hightlight Matches
//Format code - ex IBC
$display_code = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['code']);
//Format year - ex 2012
$display_year = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['year']);
//Format Chapter - ex Means Of Egress
$display_chapter = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['chapter']);
//Format Section - ex Stairs
$display_section = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['section']);
//Format sub Section - ex 1009.4 width
$display_sub = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['subsection']);
//$display_subsection = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['subsection']);
$display_def = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['def']);
$display_exception = preg_replace("/".$search_string."/i", "<b class='highlight'>".$search_string."</b>", $result['exception']);
$display_url = 'http://php.net/manual-lookup.php?pattern='.urlencode($result['code']).'&lang=en';
// Insert Name
$output = str_replace('nameString', $display_name, $html);
//Insert Code
$output = str_replace('codeString', $display_code, $output);
//Insert Year
$output = str_replace('yearString', $display_year, $output);
//Insert Chapter
$output = str_replace('chapterString', $display_chapter, $output);
// Insert Section
$output = str_replace('sectionString', $display_section, $output);
// Insert Sub Section
$output = str_replace('SUBHERE', $display_sub, $output);
// Insert Defenition
$output = str_replace('defString', $display_def, $output);
// Insert exceptions
$output = str_replace('exceptionString', $display_exception, $output);
// Insert URL
$output = str_replace('urlString', $display_url, $output);
// Output
echo($output);
}
}else{
// Format No Results Output
$output = str_replace('urlString', 'javascript:void(0);', $html);
$output = str_replace('nameString', '<b>No Results Found.</b>', $output);
$output = str_replace('functionString', 'Sorry :(', $output);
// Output
echo($output);
}
}
?>
As others are pointing out, you need to use a LIKE condition for each word in the search.
So, as a first approach to the problem, split your input like this:
$search_string = 'jump lazy dog';
$search_terms = explode(' ', $search_string);
$query = 'SELECT *
FROM search
WHERE ';
foreach($search_terms as $term) {
$query .= '(subsection LIKE "%'.$term.'%" OR def LIKE "%'.$term.'%" OR exception LIKE "%'.$term.'%") AND ';
}
$query = substr($query, 0, -4).'ORDER BY subsection ASC';
echo $query;
This will produce the query you need:
SELECT *
FROM search
WHERE (subsection LIKE "%jump%" OR def LIKE "%jump%" OR exception LIKE "%jump%")
AND (subsection LIKE "%lazy%" OR def LIKE "%lazy%" OR exception LIKE "%lazy%")
AND (subsection LIKE "%dog%" OR def LIKE "%dog%" OR exception LIKE "%dog%")
ORDER BY subsection ASC
(I added line breaks and indentation just to make this easier to read.)
There is a huge problem here, however: this is horrifically insecure, due to the risk of SQL injection. You need to use prepared statements to prevent this. See this help page for a variety of approaches to this.
Use parenthesis for more than 2 parameters for the WHERE statement.
$query = 'SELECT * FROM search WHERE (subsection LIKE "%'.$search_string.'%" OR def LIKE "%'.$search_string.'%" OR exception LIKE "%'.$search_string.'%") ORDER BY subsection ASC';
For each word have LIKE %word% OR LIKE %word2% etc constructs as #iamde_coder suggested
Use boolean search as #fred-ii suggested
Use specialized search-servers that split words based on language, get rid of stop-words etc. For example SOLR or sphinx
The search engine I'm using is a MySQL/PHP search engine.
I have been searching the forums for some time to try to get a solution for this problem.
If I have keywords for 3 separate images labeled:
#1 pure black
#2 pure white
#3 pure green
If I type "pure white" in the search box all 3 images come up because they all share the word "pure".
Is there a workaround or code I can add to only match exact search phrases when using multiple search keywords?
This is the code:
<?php
//get data
$button = $_GET['submit'];
$search = $_GET['search'];
$s = $_GET['s'];
if (!$s)
$s = 0;
$e = 10;
$next = $s + $e;
$prev = $s - $e;
if (strlen($search) <= 2)
echo "Must be greater then 3 chars";
else {
echo "<br /><table><tr><td><img src='juzzy.jpg' /></td><td><form action='search.php' method='GET'><input type='text' onclick=value='' size='50' name='search' value='$search'> <input type='submit' name='submit' value='Search'></form></td></tr></table>";
//connect to database
mysql_connect("","","");
mysql_select_db("");
//explode out search term
$search_exploded = explode(" ",$search);
foreach($search_exploded as $search_each) {
//construct query
$x++;
if ($x == 1)
$construct .= "keywords LIKE '%$search_each%'";
else
$construct .= " OR keywords LIKE '%$search_each%'";
}
//echo outconstruct
$constructx = "SELECT * FROM searchengine WHERE $construct";
$construct = "SELECT * FROM searchengine WHERE $construct ORDER BY keywords LIMIT $s,$e ";
$run = mysql_query($constructx);
$foundnum = mysql_num_rows($run);
$run_two = mysql_query("$construct");
if ($foundnum == 0)
echo "No results found for <b>$search</b>";
else {
echo "<table bgcolor='#0000FF' width='100%' height='1px'><br /></table><table bgcolor='#f0f7f9' width='100%' height='10px'><tr><td><div align='right'>Showing 1-10 of <b>$foundnum</b> results found for <b>$search.</b></div></td></tr></table><p>";
while ($runrows = mysql_fetch_assoc($run_two)) {
//get data
$title = $runrows['title'];
$desc = $runrows['description'];
$url = $runrows['url'];
echo "<table width='300px'>
<h4><a href='http://$url'><b>$title</b></a><br />
$desc<br>
<font color='00CC00'>$url</font></table></h4>";
}
?>
<table width='100%'>
<tr>
<td>
<div align="center">
<?php
if (!$s<=0)
echo "<a href='search.php?search=$search&s=$prev'>Prev</a>";
$i =1;
for ($x=0;$x<$foundnum;$x=$x+$e) {
echo " <a href='search.php?search=$search&s=$x'>$i</a> ";
$i++;
}
if ($s<$foundnum-$e)
echo "<a href='search.php?search=$search&s=$next'>Next</a>";
}
}
?>
</div>
</td>
</tr>
</table>
Don't explode your search string. This will force it to use the full search string as a search, rather than any one of the pieces.
Or, you could change your operator OR in your construct to AND, and that way it would require all the words to appear, regardless of order, however.
Don't use fuzzy LIKE %% queries, query by keywords = '$search'.