summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Coevoet <stof@notk.org>2012-01-09 18:18:57 +0100
committerChristophe Coevoet <stof@notk.org>2012-01-09 18:18:57 +0100
commitc8594d6018dd2386e67952a99ee8d672007028f5 (patch)
treea22c5962abb024e5042f634baa0d0083f2125945
parentf726a8f72ea77ddcfb143854dad68c1108d61346 (diff)
Added the support of NOT in the boolean engine
-rw-r--r--app/Resources/views/boolean_search.html.twig1
-rw-r--r--src/Riu/Search/BooleanEngine.php25
-rw-r--r--src/Riu/Search/Matcher.php5
-rw-r--r--src/Riu/Search/MatcherInterface.php5
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();
}