Reputation: 31
I have a database of book titles and would like the user to be able to search for the titles without having to use their search terms in the exact order of the title. The search is done using a form which queries the database
For example: I want them to be able to search Pride and Prejudice by asking for "Pride Prejudice" or "Prejudice Pride" instead of typing "pride and prejudice".
I tried using REGEXP and exploding the search terms and then imploding them with an OR operator (|) [gives me everything with the word "and" when searching pride and prejudice], (+) and (.*) to no avail.
Upvotes: 3
Views: 3239
Reputation: 562791
If you need sophisticated search features, use a fulltext search solution.
In MySQL, the builtin fulltext search index feature works in MyISAM and InnoDB storage engines. InnoDB is the default since 2010, and the preferred engine in virtually all cases.
You could also use an external solution like Sphinx Search or Apache Solr to provide fulltext search capabilities externally to the database. There's even a way to use a Sphinx Search index via the MySQL pluggable storage engine interface.
I don't like using LIKE
with wildcards or REGEXP
for fulltext searches. These solutions incur full table scans for every search, and depending on the volume of your data, run hundreds or thousands of times slower than if you have an index.
I wrote a comparison of fulltext search solutions for MySQL in my presentation, "Practical Full-Text Search in MySQL," and also in a chapter of my book SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
Upvotes: 4
Reputation: 2528
To match all:
$keywords = $_POST['keywords'];
$keys = preg_replace('!\s+!', '|', $keywords);
$count = count(explode('|',$keys));
$regexp = "(($keys).*){{$count}}";
$query = "SELECT * FROM table WHERE column REGEXP '$regexp'";
Upvotes: 0
Reputation: 31
This should be what your looking for:
$search_terms = trim($_GET['search']);
$search_terms = explode(" ",$search_terms);
$match_size = sizeof($search_terms);
$search = "";
for ($x=0;$x<$match_size$x++){
if($x>0)
$search = $search."|".$search_terms[$x];
else
$search = trim($search_terms[$x]);
}
select * from TABLE where FIELD regexp '(($search).*){{$match_size}}';";
Upvotes: 3
Reputation: 2865
Usually in normal Regular expressions you would just do (?=regA)(?=regB)
but this doesn't work in MySQL now. My solution to this problem was to just add an AND statement in the MySQL statement. Although when automatically generated, semantically not a nice solution in your case.
SELECT * FROM table WHERE column REGEXP 'regA' AND column REGEXP 'regB'
Upvotes: 0
Reputation: 71939
I don't think you need REGEXP here. You could try something like ... WHERE title LIKE '%prejudice%' AND title LIKE '%pride%'
.
Upvotes: 1