diff options
author | Christophe Coevoet <stof@notk.org> | 2012-01-09 18:18:57 +0100 |
---|---|---|
committer | Christophe Coevoet <stof@notk.org> | 2012-01-09 18:18:57 +0100 |
commit | c8594d6018dd2386e67952a99ee8d672007028f5 (patch) | |
tree | a22c5962abb024e5042f634baa0d0083f2125945 | |
parent | f726a8f72ea77ddcfb143854dad68c1108d61346 (diff) |
Added the support of NOT in the boolean engine
-rw-r--r-- | app/Resources/views/boolean_search.html.twig | 1 | ||||
-rw-r--r-- | src/Riu/Search/BooleanEngine.php | 25 | ||||
-rw-r--r-- | src/Riu/Search/Matcher.php | 5 | ||||
-rw-r--r-- | src/Riu/Search/MatcherInterface.php | 5 |
4 files changed, 34 insertions, 2 deletions
diff --git a/app/Resources/views/boolean_search.html.twig b/app/Resources/views/boolean_search.html.twig index d61dc23..8a3d5f0 100644 --- a/app/Resources/views/boolean_search.html.twig +++ b/app/Resources/views/boolean_search.html.twig @@ -12,6 +12,7 @@ <label for="search">Critère:</label> <input type="search" name="q" value="{{ query|default('') }}" id="search" /> <span class="help-block"> + Pour faire un NON logique, préfixez le mot par un -.<br /> Pour faire un ET logique, séparez les mots par un +.<br /> Pour faire un OU logique, séparez les par une espace. </span> diff --git a/src/Riu/Search/BooleanEngine.php b/src/Riu/Search/BooleanEngine.php index bf2f478..d823f8f 100644 --- a/src/Riu/Search/BooleanEngine.php +++ b/src/Riu/Search/BooleanEngine.php @@ -19,7 +19,7 @@ class BooleanEngine implements EngineInterface */ public function search($query) { - if (!preg_match('/^[\+ \w]*$/i', $query)) { + if (!preg_match('/^[\+\- \w]*$/i', $query)) { throw new InvalidQueryException('The query is invalid'); } $orClauses = explode(' ', $query); @@ -32,8 +32,13 @@ class BooleanEngine implements EngineInterface private function handleAndQuery($query) { $result = null; - $andClauses = explode('+', $query); + $notClauses = array(); + $andClauses = array_filter(explode('+', $query)); foreach ($andClauses as $clause) { + if ('-' === $clause[0]) { + $notClauses[] = substr($clause, 1); + continue; + } $uses = $this->matcher->getWordUses($clause); if (null === $result) { $result = $uses; @@ -47,6 +52,22 @@ class BooleanEngine implements EngineInterface } } + // Handle removal for not clauses + if (!empty($notClauses)) { + if (null === $result) { + $result = array_flip($this->matcher->getDocumentIds()); + } + + foreach ($notClauses as $clause) { + $uses = $this->matcher->getWordUses($clause); + foreach ($uses as $id => $frequency) { + if (isset($result[$id])) { + unset($result[$id]); + } + } + } + } + return array_keys($result); } } diff --git a/src/Riu/Search/Matcher.php b/src/Riu/Search/Matcher.php index 24cc897..899af8d 100644 --- a/src/Riu/Search/Matcher.php +++ b/src/Riu/Search/Matcher.php @@ -65,6 +65,11 @@ class Matcher implements MatcherInterface return $this->documents; } + public function getDocumentIds() + { + return array_keys($this->getDocuments()); + } + private function getWords() { if (null === $this->words) { diff --git a/src/Riu/Search/MatcherInterface.php b/src/Riu/Search/MatcherInterface.php index a59812c..019cfd3 100644 --- a/src/Riu/Search/MatcherInterface.php +++ b/src/Riu/Search/MatcherInterface.php @@ -20,4 +20,9 @@ interface MatcherInterface * @return \Riu\Search\Document[] */ function getDocuments(); + + /** + * @return array + */ + function getDocumentIds(); } |