Development

Changeset 27063

You must first sign up to be able to contribute.

Changeset 27063

Show
Ignore:
Timestamp:
01/22/10 18:40:27 (3 years ago)
Author:
rande
Message:

[sfSolrPlugin] add query analyser/guesser

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/sfSolrPlugin/branches/sf1.2/lib/util/sfLuceneCriteria.class.php

    r26834 r27063  
    3737    TYPE_NONE = '', 
    3838    TYPE_AND  = 'AND', 
    39     TYPE_OR   = 'OR'; 
     39    TYPE_OR   = 'OR', 
     40    TYPE_DEFAULT = ' '; // default use the default separator defined in the schema.xml file 
    4041 
    4142   
     
    177178  } 
    178179   
     180  public function guessParts($phrase) 
     181  { 
     182    // initialize variable 
     183     $phrase = trim($phrase); 
     184     $phrase = str_replace('""', '', $phrase); 
     185     $phrase = str_replace('\'\'', '', $phrase); 
     186 
     187     $default_separators = array(' ', ','); 
     188     $phrase_separators  = array('\'', '"'); 
     189     $separators = array_merge($default_separators, $phrase_separators); 
     190     $separator = $default_separators; 
     191 
     192     $current_phrase = ""; 
     193     $contains       = 'contains'; 
     194 
     195     $parts = array( 
     196       'must_contains' => array(), 
     197       'must_not_contains' => array(), 
     198       'contains' => array(), 
     199     ); 
     200 
     201     for($i = 0; $i < strlen($phrase); $i++) 
     202     { 
     203       $char = $phrase{$i}; 
     204 
     205 
     206       if(strlen($current_phrase) == 0) 
     207       { 
     208 
     209         if($char == '-') 
     210         { 
     211           $contains = 'must_not_contains'; 
     212           continue; 
     213         }  
     214         elseif($char == '+') 
     215         { 
     216           $contains = 'must_contains'; 
     217           continue; 
     218         } 
     219 
     220         if(in_array($char, $phrase_separators)) 
     221         { 
     222           $separator = array($char); 
     223           continue; 
     224         }  
     225         else if(in_array($char, $default_separators)) 
     226         { 
     227           $separator = $default_separators; 
     228 
     229           continue; 
     230         } 
     231       } 
     232 
     233       // end of the phrase 
     234       if(strlen($current_phrase) > 0 && (in_array($char, $separator) || strlen($phrase) - 1 == $i)) 
     235       { 
     236 
     237         if(strlen($phrase) - 1 == $i && !in_array($char, $separator)) 
     238         { 
     239           $current_phrase .= $char; 
     240         } 
     241 
     242         $parts[$contains][] = $current_phrase; 
     243 
     244         // restore default values 
     245         $contains       = 'contains'; 
     246         $current_phrase = ''; 
     247         $separator      = $default_separators; 
     248 
     249         continue; 
     250       } 
     251 
     252       $current_phrase .= $char; 
     253     } 
     254      
     255     return $parts; 
     256  } 
     257  /** 
     258   * This method try to parse the provided $phrase into a valid solr query 
     259   * The method can handle +/- and quote grouping 
     260   * 
     261   * @param string $phrase  
     262   * @return sfLuceneCriteria  
     263   */ 
     264  public function addPhraseGuess($full_phrase) 
     265  { 
     266 
     267    foreach($this->guessParts($full_phrase) as $section => $phrases) 
     268    { 
     269      if(count($phrases) == 0) 
     270      { 
     271         
     272        continue; 
     273      } 
     274 
     275      $inner_type = ($section == 'must_contains' || $section == 'must_not_contains') ? 'AND' : 'OR'; 
     276      $sign       = ($section == 'must_contains' ? '+' : ($section == 'must_not_contains' ? '-' : '')); 
     277       
     278      $c = new sfLuceneCriteria; 
     279      foreach($phrases as $phrase) 
     280      { 
     281        $c->addPhrase($phrase, $inner_type); 
     282      } 
     283       
     284      $this->add($sign.'('.$c->getQuery().')', 'AND', true);  
     285    } 
     286     
     287    return $this; 
     288  } 
     289   
     290  /** 
     291   * This method try to parse the provided $phrase into a valid solr query 
     292   * The method can handle +/- and quote grouping 
     293   * 
     294   * @param string $field  
     295   * @param string $phrase  
     296   * @return sfLuceneCriteria  
     297   */ 
     298  public function addPhraseFieldGuess($field, $full_phrase, $type = sfLuceneCriteria::TYPE_AND) 
     299  { 
     300 
     301    $main_criteria = new sfLuceneCriteria; 
     302    foreach($this->guessParts($full_phrase) as $section => $phrases) 
     303    { 
     304      if(count($phrases) == 0) 
     305      { 
     306         
     307        continue; 
     308      } 
     309 
     310      $inner_type = ($section == 'must_contains' || $section == 'must_not_contains') ? 'AND' : 'OR'; 
     311      $sign       = ($section == 'must_contains' ? '+' : ($section == 'must_not_contains' ? '-' : '')); 
     312       
     313      $c = new sfLuceneCriteria; 
     314      foreach($phrases as $phrase) 
     315      { 
     316        $c->addPhrase($phrase, $inner_type); 
     317      } 
     318       
     319      $main_criteria->add($sign.'('.$c->getQuery().')', 'AND', true);  
     320    } 
     321     
     322    $this->addField($field, $main_criteria, $type, true); 
     323     
     324    return $this; 
     325  } 
     326   
    179327  public function addField($field, $query, $type = sfLuceneCriteria::TYPE_AND, $force = false) 
    180328  { 
     
    273421   * @return sfLuceneCriteria 
    274422   */ 
    275   public function addPhrase($phrase, $type = sfLuceneCriteria::TYPE_AND
     423  public function addPhrase($phrase, $type = sfLuceneCriteria::TYPE_AND, $clever = false
    276424  { 
    277425     
     
    611759  public static function sanitize($keyword) 
    612760  { 
    613  
     761    $keyword = str_replace('"', '', $keyword); 
    614762    return sfLuceneApacheSolrService::phrase($keyword); 
    615763  } 
  • plugins/sfSolrPlugin/branches/sf1.2/test/unit/util/sfLuceneCriteriaTest.php

    r26834 r27063  
    8787$s = $criteria->getQuery(); 
    8888 
    89 $t->cmp_ok($s, '===', '("test") AND ("&\\"" OR "?" OR "\\\\unsafe")', '::addSane() with standard string'); 
     89$t->cmp_ok($s, '===', '("test") AND ("&" OR "?" OR "\\\\unsafe")', '::addSane() with standard string'); 
    9090 
    9191try { 
     
    169169$t->cmp_ok($s, '===', $expected, '->add() with empty string'); 
    170170 
     171$t->diag('testing addPhraseGuess()'); 
     172 
     173$s = inst()->addPhraseGuess('Thomas -"zend framework"')->getQuery(); 
     174$expected = '-("zend framework") AND ("Thomas")'; 
     175$t->cmp_ok($s, '===', $expected, '->addPhraseGuess()'); 
     176 
     177$s = inst()->addPhraseGuess('"Thomas"   -"zend framework"')->getQuery(); 
     178$expected = '-("zend framework") AND ("Thomas")'; 
     179$t->cmp_ok($s, '===', $expected, '->addPhraseGuess()'); 
     180 
     181$s = inst()->addPhraseGuess('"Thomas"   -.zend')->getQuery(); 
     182$expected = '-(".zend") AND ("Thomas")'; 
     183$t->cmp_ok($s, '===', $expected, '->addPhraseGuess()'); 
     184 
     185$s = inst()->addPhraseGuess('Thomas Rabaix +"symfony expert" -"zend framework" +javascript -.net')->getQuery(); 
     186$expected = '+("symfony expert" AND "javascript") AND -("zend framework" AND ".net") AND ("Thomas" OR "Rabaix")'; 
     187$t->cmp_ok($s, '===', $expected, '->addPhraseGuess()'); 
     188 
     189$s = inst()->addPhraseGuess('Thomas Rabaix +"sym"fony expert" -"zen-d framework" +javascript -.net')->getQuery(); 
     190$expected = '+("sym" AND "javascript") AND -("zen-d framework" AND ".net") AND ("Thomas" OR "Rabaix" OR "fony" OR "expert")'; 
     191$t->cmp_ok($s, '===', $expected, '->addPhraseGuess()'); 
     192 
     193$s = inst()->addPhraseFieldGuess('name', 'Thomas Rabaix +"sym"fony expert" -"zen-d framework" +javascript -.net')->getQuery(); 
     194$expected = 'name:((+("sym" AND "javascript") AND -("zen-d framework" AND ".net") AND ("Thomas" OR "Rabaix" OR "fony" OR "expert")))'; 
     195$t->cmp_ok($s, '===', $expected, '->addPhraseGuess()'); 
     196 
     197 
     198