diff --git a/Resources/config/sphinxsearch.xml b/Resources/config/sphinxsearch.xml index 4cb8a8a..b71f820 100644 --- a/Resources/config/sphinxsearch.xml +++ b/Resources/config/sphinxsearch.xml @@ -16,7 +16,7 @@ - %kernel.root_dir%/../src/Search/SphinxsearchBundle/Services/Search/SphinxAPI.php + %kernel.root_dir%/../vendor/chrisapl/search-sphinxsearchbundle/Search/SphinxsearchBundle/Services/Search/SphinxAPI.php %search.sphinxsearch.searchd.host% %search.sphinxsearch.searchd.port% %search.sphinxsearch.searchd.socket% diff --git a/Services/Indexer/Indexer.php b/Services/Indexer/Indexer.php index 1775fbe..6aedcc6 100644 --- a/Services/Indexer/Indexer.php +++ b/Services/Indexer/Indexer.php @@ -2,7 +2,7 @@ namespace Search\SphinxsearchBundle\Services\Indexer; -use Assetic\Util\ProcessBuilder; +use Symfony\Component\Process\ProcessBuilder; class Indexer { @@ -65,6 +65,7 @@ public function rotate($indexes) if( is_array($indexes) ) { foreach( $indexes as &$label ) { if( isset($this->indexes[$label]) ) + $pb->add($this->indexes[$label]['index_name']); } } elseif( is_string($indexes) ) { diff --git a/Services/Search/SearchTest.php b/Services/Search/SearchTest.php new file mode 100644 index 0000000..73dced1 --- /dev/null +++ b/Services/Search/SearchTest.php @@ -0,0 +1,168 @@ +\tconnect to searchd at host HOST\n" ); + print ( "-p, --port\t\tconnect to searchd at port PORT\n" ); + print ( "-i, --index \tsearch through index(es) specified by IDX\n" ); + print ( "-s, --sortby \tsort matches by 'CLAUSE' in sort_extended mode\n" ); + print ( "-S, --sortexpr \tsort matches by 'EXPR' DESC in sort_expr mode\n" ); + print ( "-a, --any\t\tuse 'match any word' matching mode\n" ); + print ( "-b, --boolean\t\tuse 'boolean query' matching mode\n" ); + print ( "-e, --extended\t\tuse 'extended query' matching mode\n" ); + print ( "-ph,--phrase\t\tuse 'exact phrase' matching mode\n" ); + print ( "-f, --filter \tfilter by attribute 'ATTR' (default is 'group_id')\n" ); + print ( "-fr,--filterrange \n\t\t\tadd specified range filter\n" ); + print ( "-v, --value \tadd VAL to allowed 'group_id' values list\n" ); + print ( "-g, --groupby \tgroup matches by 'EXPR'\n" ); + print ( "-gs,--groupsort \tsort groups by 'EXPR'\n" ); + print ( "-d, --distinct \tcount distinct values of 'ATTR''\n" ); + print ( "-l, --limit \tretrieve COUNT matches (default: 20)\n" ); + print ( "--select \tuse 'EXPRLIST' as select-list (default: *)\n" ); + exit; +} + +$args = array(); +foreach ( $_SERVER["argv"] as $arg ) + $args[] = $arg; + +$cl = new SphinxClient (); + +$q = ""; +$sql = ""; +$mode = SPH_MATCH_ALL; +$host = "localhost"; +$port = 9312; +$index = "*"; +$groupby = ""; +$groupsort = "@group desc"; +$filter = "group_id"; +$filtervals = array(); +$distinct = ""; +$sortby = ""; +$sortexpr = ""; +$limit = 20; +$ranker = SPH_RANK_PROXIMITY_BM25; +$select = ""; +for ( $i=0; $iSetFilterRange ( $args[++$i], $args[++$i], $args[++$i] ); + else if ( $arg=="-r" ) + { + $arg = strtolower($args[++$i]); + if ( $arg=="bm25" ) $ranker = SPH_RANK_BM25; + if ( $arg=="none" ) $ranker = SPH_RANK_NONE; + if ( $arg=="wordcount" )$ranker = SPH_RANK_WORDCOUNT; + if ( $arg=="fieldmask" )$ranker = SPH_RANK_FIELDMASK; + if ( $arg=="sph04" ) $ranker = SPH_RANK_SPH04; + } + else + $q .= $args[$i] . " "; +} + +//////////// +// do query +//////////// + +$cl->SetServer ( $host, $port ); +$cl->SetConnectTimeout ( 1 ); +$cl->SetArrayResult ( true ); +$cl->SetMatchMode ( $mode ); +if ( count($filtervals) ) $cl->SetFilter ( $filter, $filtervals ); +if ( $groupby ) $cl->SetGroupBy ( $groupby, SPH_GROUPBY_ATTR, $groupsort ); +if ( $sortby ) $cl->SetSortMode ( SPH_SORT_EXTENDED, $sortby ); +if ( $sortexpr ) $cl->SetSortMode ( SPH_SORT_EXPR, $sortexpr ); +if ( $distinct ) $cl->SetGroupDistinct ( $distinct ); +if ( $select ) $cl->SetSelect ( $select ); +if ( $limit ) $cl->SetLimits ( 0, $limit, ( $limit>1000 ) ? $limit : 1000 ); +$cl->SetRankingMode ( $ranker ); +$res = $cl->Query ( $q, $index ); + +//////////////// +// print me out +//////////////// + +if ( $res===false ) +{ + print "Query failed: " . $cl->GetLastError() . ".\n"; + +} else +{ + if ( $cl->GetLastWarning() ) + print "WARNING: " . $cl->GetLastWarning() . "\n\n"; + + print "Query '$q' retrieved $res[total] of $res[total_found] matches in $res[time] sec.\n"; + print "Query stats:\n"; + if ( is_array($res["words"]) ) + foreach ( $res["words"] as $word => $info ) + print " '$word' found $info[hits] times in $info[docs] documents\n"; + print "\n"; + + if ( is_array($res["matches"]) ) + { + $n = 1; + print "Matches:\n"; + foreach ( $res["matches"] as $docinfo ) + { + print "$n. doc_id=$docinfo[id], weight=$docinfo[weight]"; + foreach ( $res["attrs"] as $attrname => $attrtype ) + { + $value = $docinfo["attrs"][$attrname]; + if ( $attrtype==SPH_ATTR_MULTI || $attrtype==SPH_ATTR_MULTI64 ) + { + $value = "(" . join ( ",", $value ) .")"; + } else + { + if ( $attrtype==SPH_ATTR_TIMESTAMP ) + $value = date ( "Y-m-d H:i:s", $value ); + } + print ", $attrname=$value"; + } + print "\n"; + $n++; + } + } +} + +// +// $Id$ +// + +?> diff --git a/Services/Search/Sphinxsearch.php b/Services/Search/Sphinxsearch.php index 68d4c86..fdfa9f7 100644 --- a/Services/Search/Sphinxsearch.php +++ b/Services/Search/Sphinxsearch.php @@ -119,8 +119,11 @@ public function search($query, array $indexes, $escapeQuery = true) if( $escapeQuery ) $query = $this->sphinx->escapeString($query); + $indexnames = ''; $results = array(); + $i = 0; foreach( $indexes as $label => $options ) { + /** * Ensure that the label corresponds to a defined index. */ @@ -131,7 +134,7 @@ public function search($query, array $indexes, $escapeQuery = true) * Set the offset and limit for the returned results. */ if( isset($options['result_offset']) && isset($options['result_limit']) ) - $this->sphinx->setLimits($options['result_offset'], $options['result_limit']); + $this->sphinx->setLimits($options['result_offset'], $options['result_limit'], 100000); /** * Weight the individual fields. @@ -139,14 +142,24 @@ public function search($query, array $indexes, $escapeQuery = true) if( isset($options['field_weights']) ) $this->sphinx->setFieldWeights($options['field_weights']); - /** - * Perform the query. - */ - $results[$label] = $this->sphinx->query($query, $this->indexes[$label]); - if( $results[$label]['status'] !== SEARCHD_OK ) - throw new \RuntimeException(sprintf('Searching index "%s" for "%s" failed with error "%s".', $label, $query, $this->sphinx->getLastError())); + /* + * Create string of index names for SphinxAPI query function. + */ + if($i == 1){ + $indexnames .= ' '; + } + $indexnames .= $this->indexes[$label]; + $i++; } + /** + * Perform the query. + */ + $results = $this->sphinx->query($query, $indexnames); + + if( $results['status'] !== SEARCHD_OK ) + throw new \RuntimeException(sprintf('Searching index "%s" for "%s" failed with error "%s".', $label, $query, $this->sphinx->getLastError())); + /** * If only one index was searched, return that index's results directly. */ @@ -158,4 +171,67 @@ public function search($query, array $indexes, $escapeQuery = true) */ return $results; } + + /** + * Reset all previously set filters. + * + */ + public function resetFilters() { + $this->sphinx->resetFilters(); + } + + /** + * Adds query with the current settings to multi-query batch. This method doesn't affect current settings (sorting, filtering, grouping etc.) in any way. + * @param string $query The query string that we are searching for. + * @param array $indexes The indexes to perform the search on. + * + * $indexes = array( + * 'IndexLabel', + * 'IndexLabel2' + * ); + */ + public function addQuery($search_str, $indexes) { + $indexnames = ''; + + //Create string on index names + foreach( $indexes as $label) { + + /** + * Ensure that the label corresponds to a defined index. + */ + if(isset($this->indexes[$label])){ + + /* + * Create string of index names for SphinxAPI query function. + */ + $indexnames .= $this->indexes[$label].' '; + } + } + + $this->sphinx->addQuery($search_str, $indexnames); + } + + /** + * Connects to searchd, runs a batch of all queries added using SphinxClient::addQuery, obtains and returns the result sets. + * + */ + public function runQueries() { + return $this->sphinx->runQueries(); + } + + /** + * Set sort mode for search. + * @param $mode Sortmode as specifed in Sphinx API Doc on of: + * SPH_SORT_RELEVANCE Sort by relevance in descending order (best matches first). + * SPH_SORT_ATTR_DESC Sort by an attribute in descending order (bigger attribute values first). + * SPH_SORT_ATTR_ASC Sort by an attribute in ascending order (smaller attribute values first). + * SPH_SORT_TIME_SEGMENTS Sort by time segments (last hour/day/week/month) in descending order, and then by relevance in descending order. + * SPH_SORT_EXTENDED Sort by SQL-like combination of columns in ASC/DESC order. + * SPH_SORT_EXPR + * @param $sortby String name of field to sort. + */ + public function setSortMode($mode, $sortby){ + $this->sphinx->setSortMode($mode, $sortby); + } } + diff --git a/composer.json b/composer.json index 8fa3328..ea143d7 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,9 @@ { - "name": "search/sphinxsearch-bundle", + "name": "chrisapl/search-sphinxsearchbundle", "type": "symfony-bundle", "description": "Sphinx search bundle for Symfony 2", "keywords": ["sphinx", "sphinxsearch", "symfony2"], - "homepage": "https://github.com/timewasted/Search-SphinxsearchBundle", + "homepage": "https://github.com/chrisapl/Search-SphinxsearchBundle", "license": "BSD-2-Clause", "authors": [ {