Creating a search engine - php

I'm trying to create a search engine to search for users based on their name.
Here is an example of what I can do at this moment:
I want to search for david (surname) Jones (name)
-> When I type: 'Da' or 'vid' or 'J' or 'ones' it gives me David Jones
BUT when I type 'David J' it gives nothing.
In which way do I have to change my query to search on both fields on the same time?
The query:
public function Search($searchinput)
{
$db = new Db();
$select = "SELECT * FROM tblusers WHERE name LIKE '%" . $searchinput . "%' OR surname LIKE'%" . $searchinput . "%'";
$result = $db->conn->query($select);
return $result;
}

probably for production you can use http://sphinxsearch.com/ because it is MUCH faster than MySQL in searching texts in natural language

Try this query using CONCAT:
$select = "SELECT * FROM tblusers WHERE name LIKE '%". $searchinput ."%' OR surname LIKE '%". $searchinput ."%' OR CONCAT(name,' ',surname) LIKE '%". $searchinput ."%' ";

The problem is that you are trying to match David J in name or surname but as I see your db look as like follows:
Name | Surnam
Davud | Jones
And your like statement is looking for: "David J" into name or surname which give you the right result(zero) because there does not exist any row with name or surname like "David J", in your case the best solution will be to concat the name with surname and then to make like statment upon them:
Select * FROM tbulsers WHERE CONCAT(name, ' ', surname) LIKE "%David J%"

Related

php MySql query `LIKE '$word'` returns NULL

In the code below the
var_dump($row);
shows NULL
$query = "SELECT * FROM maintable WHERE Category LIKE '$word'
OR Title LIKE '$word'
OR Title2 LIKE '$word'
OR Description LIKE '$word'
OR Description2 LIKE '$word'
OR Preimushestva LIKE '$word'
OR Preimspisok LIKE '$word';";
$result = mysqli_query($link, $query)
or die("Error: ".mysqli_error($link));
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
var_dump($row);
and $word = 'dolor'
and I have word dolor in my table, in Description tab help me find mistake please
You're missing your pattern matching characters. Without them LIKE is essentially the same as =.
Here's an example:
$query = "SELECT * FROM maintable WHERE Category LIKE '%$word%'
OR Title LIKE '%$word%'
OR Title2 LIKE '%$word%'
OR Description LIKE '%$word%'
OR Description2 LIKE '%$word%'
OR Preimushestva LIKE '%$word%'
OR Preimspisok LIKE '%$word%';";
Look at this link : http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_like
$query = "SELECT * FROM maintable
WHERE Category LIKE '%".$word."%'
OR Title LIKE '%".$word."%'
OR Title2 LIKE '%".$word."%'
OR Description LIKE '%".$word."%'
OR Description2 LIKE '%".$word."%'
OR Preimushestva LIKE '%".$word."%'
OR Preimspisok LIKE '%".$word."%';";
My best guess would be that you need to search for '%dolor%'. The expression like without any wild card characters searches for an exact match.
However, it would help if you printed out the query after the variable substitution. You can edit your question with this information if the wildcard form doesn't fix your problem.

PHP MySQL While Loop Multiple tables

Morning peps!
I'm having some troubles getting my query to work properly. I've created a search field which pulls rows from multiple tables (invoices, customers). For example, when ever I'm searching for invoice "2014-003", which is the only invoice with that nr., then I'm getting a list of all of my customers and then the same invoice nr. all the way down..
My code:
$results = $db->query("SELECT * FROM invoices, customers
WHERE invoice.customer_id = customers.id AND
(customers.name LIKE '%" . $search . "%') OR
(invoices.invoice_nr LIKE '%" . $search . "%') OR
(invoices.email LIKE '%" . $search . "%') OR
(customers.email LIKE '%" . $search . "%')");
I suck at english, so I think it's better for me to maybe write an example below:
I'll search for the invoice nr. "2014-003" which is unique, and what I get is this:
Peter - 2014-003
Christian - 2014-003
Adam - 2014-003
Frederick - 2014-003
Peter - 2014-003
and it should return:
Adam - 2014-003
because Adam is the only one who has an invoice with the following invoice nr.
I hope you'll understand what I want to do :)
Give this a whirl:
$results = $db->query("
SELECT
*
FROM
invoices,
customers
WHERE
invoice.customer_id = customers.id AND
((customers.name LIKE '%" . $search . "%') OR
(invoices.invoice_nr LIKE '%" . $search . "%') OR
(invoices.email LIKE '%" . $search . "%') OR
(customers.email LIKE '%" . $search . "%')
)");
Your ORs are not grouped properly, hence the AND validates, but is later relaxed because it gets a hit on one of the ORs - whereas your OR's are really referring to a group of possible conditions (but the original join needs to stay in place)

Find string in two field with SQL

I'm working on a search module, like facebook when you look for a friend.
So, i have in my table user two fields : firstname and name.
If i have for example a user : firstname : Georges and name : Clooney, i want, when i write :
Geo...
Cloo...
loo geor...
geor ney
etc....
retrieve this user.
How can i do that with SQL ? I want to write a very permissive search module..
This will surely help you
Well the below method first calculate all possible combination of the possible words & then matches it with database
<?php
$name ='Georges Clooney'; // you search string
$words=explode(" ", $name);;
function get_all_combination($arr, $temp_string, &$collect) {
if ($temp_string != "")
$collect []= $temp_string;
for ($i=0; $i<sizeof($arr);$i++) {
$arrcopy = $arr;
$elem = array_splice($arrcopy, $i, 1); // removes and returns the i'th element
if (sizeof($arrcopy) > 0) {
get_all_combination($arrcopy, $temp_string ." " . $elem[0], $collect);
} else {
$collect []= $temp_string. " " . $elem[0];
}
}
}
$collect = array();
get_all_combination($words, "", $collect);
/*
$collect now have all possible combination of search string
Array
(
[0] => Georges
[1] => Georges Clooney
[2] => Clooney
[3] => Clooney Georges
)
*/
$sql="SELECT * FROM user_info WHERE (firstname like '%".implode("%' OR firstname like '%",$collect)."%' or name like '%".implode("%' OR name like '%",$collect)."%')" ;
?>
For any more help do ask
What you need, is this little Friend: %
WHERE firstname LIKE '%" . $name . "%' OR name LIKE '%" . $name ."%'
Here is a tutorial:
http://www.webreference.com/programming/php/search/index.html
Try This:
Select * from User where `name` LIKE '%search_string%' OR `firstname`
LIKE '%search_string%' OR CONCAT(firstname,' ',name) LIKE '%search_string'%'
SELECT *
FROM User
WHERE firstname LIKE '%'+#input+'%' OR name LIKE '%'+#input+'%'
where #input is the inserted text in the textbox.
Try this query:
SELECT * from user
WHERE name LIKE '%search_string%'
OR firstname LIKE '%search_string%'
It will match if any firstname or name containing search_string. it will show all users containing this string in name or first name.
Try this
select * from user where `name` like '%trim(search_string)%' OR `firstname`
like '%trim(search_string)%' OR CONCAT(firstname,' ',name) LIKE '%".trim(search_string)."%';
Also concat both the fields and try to match.

Return row if non existent in other table

I have 2 tables
members
=======
id
f_name // get these values.
l_name
email
friends
=======
to
from
The users's I'd is the value $member_id, if it is present in "to" or "from" I want it to not return the other value of that row, so only non-friends are shown.
Im creating a page to allow members to search through the database to add their friends by email, or name.
I'd like to return all rows from members where there is no record of the userid in either the "to" or "from" columns of the friends table.
I know how to do most basic mysql but joins are an issue for me, i don't really understand how to write them, if anyone can help me out and maybe even explain it a bit that would be great!
My query now:
$query = "SELECT * FROM members WHERE f_name LIKE '%" . $word . "%' OR l_name LIKE '%" . $word . "%' OR mc_name LIKE '%" . $word . "%' OR email LIKE '%" . $word . "%' LIMIT 10";
//Where $word is the search term.
Modified Query
SELECT * FROM members WHERE id NOT IN (SELECT to FROM friends WHERE frm=$member_id) AND $member_id NOT IN (SELECT frm FROM friends WHERE to=$member_id) AND f_name LIKE '%" . $word . "%' OR l_name LIKE '%" . $word . "%' OR mc_name LIKE '%" . $word . "%' OR email LIKE '%" . $word . "%' LIMIT 10
Edited
So, suppose a user with id 3:
SELECT *
FROM members
WHERE id <> 3
AND id NOT IN (SELECT to FROM friends WHERE from = 3)
AND id NOT IN (SELECT from FROM friends WHERE to = 3)
[Other conditions....];
OR
SELECT *
FROM members
LEFT JOIN friends
ON (members.id = friends.to
OR members.id = friends.from)
AND (members.to = 3
OR members.from = 3)
WHERE friends.to IS NULL
AND id <> 3
[Other conditions....];
Maybe consider change the name of your "from" and "to" columns, to avoid confusion, because FROM and TO are reserved words.
Also, you can use the reserved word EXPLAIN , before the query, to see the difference of the number of rows being fetched.
You might be able to do that using an LEFT Join, which will return all rows from members even if there's no corresponding row on the friend's table.
Something like this:
SELECT a.*, f.* FROM members m LEFT JOIN friends f
A great article to understand the many joins there are is this one.

Finding a list of comma separated keywords

When I run my code I cannot retrieve the entry that I am targeting because the keywords that are being run through the query are not the same as the keywords in the database.
Keywords:
$keywords = 'spaghetti,macaroni,hamburger';
Query:
mysql_query("SELECT * FROM ---- WHERE keywords LIKE '%$keywords%' ORDER BY id DESC LIMIT 1");
I am targeting an entry with these keywords:
food, restaurant, hamburger, spaghetti, taco,pie
I may be missing something simple here since I've been working for 12 hours straight. However, I've had no luck with anything I've tried to do to work around this issue.
From my point of view the query should be returning the target entry since there are 2 matching keywords.
What should I be doing differently?
$like = array();
$keywords = explode(',' , $keywords);
foreach($keywords as $keyword) {
$like[] = "`keywords` LIKE '%$keyword%'";
}
$like = implode(' OR ', $like);
$query = "SELECT * FROM `table` WHERE $like ORDER BY id DESC LIMIT 1";
You need to break up the keywords and do a separate LIKE comparison for each one
SELECT * FROM mytable
WHERE keywords LIKE '%spaghetti%' OR keywords LIKE '%macaroni%'
-- ...
You could do something like this
<?php
$keywords = 'spaghetti,macaroni,hamburger';
$query = "SELECT * FROM mytable WHERE 1=1";
$keywords = explode(',', $keywords);
if (count($keywords)) {
$query .= sprintf(
" AND (%s)",
implode(' OR ', array_map(function($word){
return "keywords LIKE '%{$word}%'";
}, $keywords))
);
}
echo $query;
// SELECT * FROM mytable WHERE 1=1 AND (keywords LIKE '%spaghetti%' OR keywords LIKE '%macaroni%' OR keywords LIKE '%hamburger%')
As you can see from the comments, there are better ways to handle this, but I'm assuming that this rudimentary question is looking for a simple answer.
I'm not doing any input sanitization, or adding any other fail safes. Building queries like this is not very reliable and you should continue to learn about PHP/MySQL to avoid common pitfalls in the future. However, I believe more advanced approaches are a bit out of your reach at the moment. If someone else would like to provide better techniques that they think the OP can grasp, by all means, go for it :)
Storing multiple values as a CSV inside a column is a common SQL anti-pattern. It's hard to use and even harder to optimize:
How to fix the Comma Separated List of Doom
You have to use LIKE with separeted works, you can try this:
$keywords = 'spaghetti,macaroni,hamburger';
$arrayWords = explode(',', $keywords);
$like = '';
foreach($arrayWords as $word)
$like .= empty($like) ? " keywords LIKE '%$word%' " : " OR keywords LIKE '%$word%' ";
mysql_query("SELECT * FROM ---- WHERE $like ORDER BY id DESC LIMIT 1");
mysql_query("SELECT * FROM ---- WHERE keywords LIKE '%". implode("%' OR keywords LIKE '%", explode(",", $keywords)) ."%' ORDER BY id DESC LIMIT 1");
Try this, it may be faster than using multiple or clauses
Select * from mytable
where keywords REGEXP 'spaghetti|macaroni|hamburger'

Categories