I want a search query to return results that match all keywords, but I can only get it to either match any or match string.
I.E. "cake chocolate" either returns all records with "cake" OR "chocolate" in a tag field, or results with the exact tag "cake chocolate", as opposed to what I want, which is to get any record with "cake" AND "chocolate". Here is what I've got:
$key = $this->input->post('searchTerm');
if($key != ''){
// if I comment out the next 10 lines, it becomes MATCH-ANY
$this->db->or_like('product_name',$key);
$this->db->or_like('product_code',$key);
$this->db->or_like('description',$key);
$this->db->or_like('season',$key);
$this->db->or_like('year',$key);
$this->db->or_like('photo_style',$key);
$this->db->or_like('photo_status',$key);
$this->db->or_like('extra_field1',$key);
$this->db->or_like('extra_field2',$key);
$this->db->or_like('additional_notes',$key);
// But if I comment out the next 7 lines instead, I match only the entire string.
$Singlequry = "select * from (select *, concat_ws(' ',product_name,product_code,description,season,year,photo_style,photo_status,extra_field1,extra_field2,additional_notes) merged from records )temp where ";
$keywordsMany = explode(' ',$key);
$tempQuery = array();
foreach($keywordsMany as $each){
$tempQuery[] = " temp.merged like '%".mysql_real_escape_string($each)."%'";
}
$Singlequry = $Singlequry.implode(' or ',$tempQuery); // end of search type comment-out
$makeQuery = true;
}
In case it's not obvious, I really have no idea what I'm doing. I've thrown where_in and other stuff in place of the or_like but with no luck. All this to say, I will need a little hand-holding:)
Unfortunately you cannot produce this query with codeigniter or_like;
Your current code produce your query like this
SELECT * from tablename WhHERE product_name like '%key%' or product_code like '%key%' OR..............
which will return only any match with the key.
BUT I guess you want all match which should be like this
SELECT * from tablename WhHERE product_name like '%key%' AND product_code like '%key%' AND..............
if so you can replace your or_like with where like followings
$this->db->where("product_name LIKE '%$key%'");
$this->db->where("product_code LIKE '%$key%'");
$this->db->where("description LIKE '%$key%'");
It will produce your expected query.It will return results which has all match with key.
You can do it many other way too.
Hope it will will help you.
Related
I am working on a search filter that connects to a MySQL database. It accepts a keyword parameter; however, it only searches for the keyword in the order it is typed in. For example: If I type in "house rental", it looks for the term in xyz column in the order it is typed it.
However, I would like to change it so that it searches for both those terms are independent of the order they are typed in. Example, if typed in "house rental", the result should contain listings that have either, "house rental" or "rental house" mentioned somewhere in the xyz columns.
I have tried to break the keywords, put it in an array and do a foreach loop on the array to get the result but it generates correct but undesired results. The results that are generated are not the ones that I required.
$samp_text = 'House Rental';
$split_string_array = preg_split('/[\s,]+/', $samp_text);
foreach ($split_string_array as $each_sql_query) {
print_r('SELECT * FROM XYZ WHERE $keyword LINK = %' . $each_sql_query . '% '. "\r");
}
I would like a suggestion on how to tackle this problem.
While the method Sloan Thrasher suggests works, it does not scale.
The solution is to create a table contains each keyword from a searchable document as a single row with a foreign key to the original document with an index on the search word then the foreign key. Split your search term into an equivalent table, join the 2 and count the matches:
Select doc.txt, count(*)
From doc
Inner join keywords
On doc.id=keywords.doc_id
Inner join search
On keywords.word=search.word
Where search.query_id=?
Group by doc.txt
Order by count(*) desc
Alternatively just use the built-in fulltext capability of mysql.
You can build a query that will check for all keywords at once and give you list of rows that contain all of the keywords.
If you want all rows that contain one or more keywords, change the AND in the implode function to OR.
$samp_text = 'House Rental';
$split_string_array = preg_split('/[\s,]+/', $samp_text);
$qstr = "SELECT * FROM XYZ WHERE ";
$keywords = array();
foreach ($split_string_array as $each_sql_query) {
$keywords[] = " LINK = '%" . $each_sql_query . "%'\r")
}
$qstr .= implode(" AND ",$keywords);
// Code to execute query and use results.
I have made a search bar for searching string my query is
$q = $_GET('val');
$sqlquery=$mysqli->query("SELECT * FROM tickets_search WHERE (ticket_date LIKE
'%".$q."%') OR (car_number LIKE '%".$q."%') order by ticket_id desc");
Now when I search for HU-GG 6 it gives me two results
see here:
Snippet-1 : HU-GG 6-1
When I search for HU-GG-6.it gives me another result
see here:
Snippet-2: HU-GG-6-2
What I want that is to show all three results with HU-GG-6 or HU-GG 6 whatever I write.It should show me all three results.
TRY THIS: You can use REPLACE to satisfy both of your conditions but I am not sure how much it will help and please adjust REPLACE in PHP if it's not correct:
SELECT *
FROM tickets_search
WHERE (ticket_date LIKE '%".$q."%') OR
(REPLACE(car_number, ' ', '-') LIKE REPLACE('%".$q."%', ' ', '-'))
ORDER BY ticket_id DESC
I've looked all over the interwebs, and cannot find that simple answer I'm looking for - possibly because it doesn't exist, but.. possibly because I don't know the correct terms to search for.
ok, so, i've got a variable - it's actaully a key value pair in an array that i'm passing into my function. the key is args[comments_mentioned] and the value is dynamically generated for me - it's ALWAYS going to be number, separated by commas (i.e. 1,2,3,4,5)
so, just to be super clear:
$args[comments_mentioned] == "1,2,3,4"; //could be any amount of number, not just 1,2,3,4,5
i'd like to pass this into a sql statement as a variable to use in an "IN" clause, like so:
$sr_sql = <<<SQL
SELECT *
FROM $wpdb->commentmeta
WHERE meta_value = %s
AND comment_ID in ($args[comments_mentioned])
ORDER BY meta_id DESC
SQL;
Then, Prepare it using the wordpress prepare and get results
$sr_query = $wpdb->prepare( $sr_sql, $args[user_id]) );
//receive the correct sql statement, and plug 'er in.
$sr_comment_rows = $wpdb->get_results($sr_query);
and run my foreach loop:
foreach ($sr_comment_rows as $sr_comment) {
$sResults .= 'do something with $sr_comment';
}
now, i realize the code above won't work - i can't just pass the variable in there like that. BUT, i can't pass it as a string (%s), because it wraps it in '1,2,3,45', and so it looks for the entire string, and not each number. I can't pass it as an int (%d), because of the commas...
In other posts, they mentioned create a temp table or variable, but, i'm not sure if that's the correct way to do it in mysql, or how to reference it once I do.
so, how do I do this? preference for actual code that works ;)
Thank you for reading and helping out!
One option, if you cannot normalize your data, is to enclose your string in commas such that it be ",1,2,3,4," and then you could do:
AND LOCATE( CONCAT(',',comment_ID,',') , ($args[comments_mentioned]) )
which will match if it finds a eg. ',3,' in ',1,2,3,4,' (Using 3 as an example)
I believe this should be enough:
$params = $args[comments_mentioned];
$table = $wpdb->commentmeta;
$sr_sql = "
SELECT *
FROM $table
WHERE meta_value = %s
AND comment_ID in ($params)
ORDER BY meta_id DESC
";
It will be result something like:
SELECT *
FROM table_on_variable
WHERE meta_value = %s
AND comment_ID in (1,2,3,4)
ORDER BY meta_id DESC
If your mainly issue is regarding the in clause, so you will not have problems if you use double quotes and single variable as illustrated above.
I currently use a mysql statement like the one below to search post titles.
select * from table where title like %search_term%
But problem is, if the title were like: Acme launches 5 pound burger and a user searched for Acme, it'll return a result. But if a user searched for Acme burger or Acme 5 pound, it'll return nothing.
Is there a way to get it to return results when a users searches for more than one word? Is LIKE the correct thing to use here or is there something else that can be used?
You could use a REGEXP to match any of the words in your search string:
select *
from tbl
where
title REGEXP CONCAT('[[:<:]](', REPLACE('Acme burger', ' ', '|'), ')[[:>:]]')
Please notice that this will not be very efficient. See fiddle here.
If you need to match every word in your string, you could use a query like this:
select *
from tbl
where
title REGEXP CONCAT('[[:<:]]', REPLACE('Acme burger', ' ', '[[:>:]].*[[:<:]]'), '[[:>:]]')
Fiddle here. But words have to be in the correct order (es. 'Acme burger' will match, 'burger Acme' won't). There's a REGEXP to match every word in any order, but it is not supported by MySql, unless you install an UDF that supports Perl regexp.
To search for a string against a text collection use MATCH() and AGAINST()
SELECT * FROM table WHERE MATCH(title) AGAINST('+Acme burger*')
or why not RLIKE
SELECT * FROM table WHERE TITLE RLIKE 'Acme|burger'
or LIKE searching an array, to have a compilation of $keys
$keys=array('Acme','burger','pound');
$mysql = array('0');
foreach($keys as $key){
$mysql[] = 'title LIKE %'.$key.'%'
}
SELECT * FROM table WHERE '.implode(" OR ", $mysql)
What you need to do is construct a SQL such that, for example:
select * from table where title like "%Acme%" and title like "%burger%"
In short: split the string and create one like for each part.
It might also work with replacing spaces with %, but I'm not sure about that.
The best thing is thing use perform union operation by splitting your search string based on whitespaces,
FOR Acme 5 pound,
SELECT * FROM TABLE WHERE TITLE LIKE '%ACME 5 POUND%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%ACME%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%5%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%POUND%'
Find out a way to give the first query a priority. Or pass the above one as four separate queries with some priority. I think you are using front end tp pass query to data bases, so it should be easy for you.
<?php
$search_term = 'test1 test2 test3';
$keywords = explode(" ", preg_replace("/\s+/", " ", $search_term));
foreach($keywords as $keyword){
$wherelike[] = "title LIKE '%$keyword%' ";
}
$where = implode(" and ", $wherelike);
$query = "select * from table where $where";
echo $query;
//select * from table where title LIKE '%test1%' and title LIKE '%test2%' and title LIKE '%test3%'
We have a problem with our search suggestions. Everytime we click on a suggestion at our website, it puts a space in front of the search query, which causes the query to fail.
The code that we use for the suggestions is this:
$query = $db->query("SELECT DISTINCT productnaam FROM product WHERE merk LIKE '$queryString%' LIMIT 10");
if($query) {
// While there are results loop through them - fetching an Object (i like PHP5 btw!).
while ($result = $query ->fetch_object()) {
// Format the results, im using <li> for the list, you can change it.
// The onClick function fills the textbox with the result.
// YOU MUST CHANGE: $result->value to $result->your_colum
echo '<li onClick="fill(\''.$result->merk.' '.$result->productnaam.'\');">'
.$result->merk.' '.$result->productnaam.''.'</li>';
}
} else {
echo 'ERROR: There was a problem with the query.';
Try out with trim()
$queryString = trim($queryString);
The trim() function removes whitespaces and other predefined characters from both sides of a string.
try the trim() function as Sameera Thilakasiri specified below and also update your query to something like "SELECT DISTINCT productnaam FROM product WHERE merk LIKE '%$queryString%' LIMIT 10" The percent sign on both sides will ensure that your query will select records that contain your input as opposed to records that start with your input.
bellow is some further explanation on the SQL LIKE condition that might help you out
// This query will look for records that start with "sa"
select * from table where name like 'sa%'
// This query will look for records that contain "sa"
select * from table where name like '%sa%'
// This query will look for records that end with "sa"
select * from table where name like '%sa'
hope that helps!