diff --git a/examples/1.3-basic-update.php b/examples/1.3-basic-update.php index ae9fa05ae..292964615 100644 --- a/examples/1.3-basic-update.php +++ b/examples/1.3-basic-update.php @@ -6,19 +6,19 @@ if ($_POST) { // if data is posted add it to solr - // create a new document for the data - // please note that any type of validation is missing in this example to keep it simple! - $doc = new Solarium_Document_ReadWrite(); - $doc->id = $_POST['id']; - $doc->name = $_POST['name']; - $doc->price = $_POST['price']; - // create a client instance $client = new Solarium_Client($config); // get an update query instance $update = $client->createUpdate(); + // create a new document for the data + // please note that any type of validation is missing in this example to keep it simple! + $doc = $update->createDocument(); + $doc->id = $_POST['id']; + $doc->name = $_POST['name']; + $doc->price = $_POST['price']; + // add the document and a commit command to the update query $update->addDocument($doc); $update->addCommit(); diff --git a/examples/2.5.5-edismax.php b/examples/2.5.5-edismax.php new file mode 100644 index 000000000..a778ae743 --- /dev/null +++ b/examples/2.5.5-edismax.php @@ -0,0 +1,44 @@ +createSelect(); + +// get the dismax component and set a boost query +$dismax = $query->getDisMax(); + +// override the default setting of 'dismax' to enable 'edismax' +$dismax->setQueryParser('edismax'); + +// this query is now a dismax query +$query->setQuery('memory -printer'); + +// this executes the query and returns the result +$resultset = $client->select($query); + +// display the total number of documents found by solr +echo 'NumFound: '.$resultset->getNumFound(); + +// show documents using the resultset iterator +foreach ($resultset as $document) { + + echo '
'; + + // the documents are also iterable, to get all fields + foreach($document AS $field => $value) + { + // this converts multivalue fields to a comma-separated string + if(is_array($value)) $value = implode(', ', $value); + + echo ''; + } + + echo '
' . $field . '' . $value . '
'; +} + +htmlFooter(); \ No newline at end of file diff --git a/examples/2.5.6-grouping-by-field.php b/examples/2.5.6-grouping-by-field.php new file mode 100644 index 000000000..e95b198db --- /dev/null +++ b/examples/2.5.6-grouping-by-field.php @@ -0,0 +1,53 @@ +createSelect(); +$query->setRows(50); + +// get grouping component and set a field to group by +$groupComponent = $query->getGrouping(); +$groupComponent->addField('inStock'); +// maximum number of items per group +$groupComponent->setLimit(3); +// get a group count +$groupComponent->setNumberOfGroups(true); + +// this executes the query and returns the result +$resultset = $client->select($query); + +$groups = $resultset->getGrouping(); +foreach($groups AS $groupKey => $fieldGroup) { + + echo '

'.$groupKey.'

'; + echo 'Matches: '.$fieldGroup->getMatches().'
'; + echo 'Number of groups: '.$fieldGroup->getNumberOfGroups(); + + foreach($fieldGroup AS $valueGroup) { + + echo '

'.(int)$valueGroup->getValue().'

'; + + foreach($valueGroup AS $document) { + + echo '
'; + + // the documents are also iterable, to get all fields + foreach($document AS $field => $value) + { + // this converts multivalue fields to a comma-separated string + if(is_array($value)) $value = implode(', ', $value); + + echo ''; + } + + echo '
' . $field . '' . $value . '
'; + } + } +} + +htmlFooter(); \ No newline at end of file diff --git a/examples/2.5.7-grouping-by-query.php b/examples/2.5.7-grouping-by-query.php new file mode 100644 index 000000000..5508cd1b0 --- /dev/null +++ b/examples/2.5.7-grouping-by-query.php @@ -0,0 +1,45 @@ +createSelect(); + +// get grouping component and create two query groups +$groupComponent = $query->getGrouping(); +$groupComponent->addQuery('price:[0 TO 99.99]'); +$groupComponent->addQuery('price:[100 TO *]'); +// sorting inside groups +$groupComponent->setSort('price desc'); +// maximum number of items per group +$groupComponent->setLimit(5); + +// this executes the query and returns the result +$resultset = $client->select($query); + +$groups = $resultset->getGrouping(); +foreach($groups AS $groupKey => $group) { + + echo '

'.$groupKey.'

'; + + foreach($group AS $document) { + echo '
'; + + // the documents are also iterable, to get all fields + foreach($document AS $field => $value) + { + // this converts multivalue fields to a comma-separated string + if(is_array($value)) $value = implode(', ', $value); + + echo ''; + } + + echo '
' . $field . '' . $value . '
'; + } +} + +htmlFooter(); \ No newline at end of file diff --git a/examples/3.1-add-docs.php b/examples/3.1-add-docs.php index f08efbbc7..1c5370e75 100644 --- a/examples/3.1-add-docs.php +++ b/examples/3.1-add-docs.php @@ -3,25 +3,24 @@ require('init.php'); htmlHeader(); +// create a client instance +$client = new Solarium_Client($config); + +// get an update query instance +$update = $client->createUpdate(); // create a new document for the data -$doc1 = new Solarium_Document_ReadWrite(); +$doc1 = $update->createDocument(); $doc1->id = 123; $doc1->name = 'testdoc-1'; $doc1->price = 364; // and a second one -$doc2 = new Solarium_Document_ReadWrite(); +$doc2 = $update->createDocument(); $doc2->id = 124; $doc2->name = 'testdoc-2'; $doc2->price = 340; -// create a client instance -$client = new Solarium_Client($config); - -// get an update query instance -$update = $client->createUpdate(); - // add the documents and a commit command to the update query $update->addDocuments(array($doc1, $doc2)); $update->addCommit(); diff --git a/examples/6.2-escaping.php b/examples/6.2-escaping.php index b311a94de..8f379e9c0 100644 --- a/examples/6.2-escaping.php +++ b/examples/6.2-escaping.php @@ -13,6 +13,7 @@ $input = 'ATA "133'; // in this case phrase escaping is used (most common) but you can also do term escaping, see the manual +// also note that the same can be done using the placeholder syntax, see example 6.3 $helper = $query->getHelper(); $query->setQuery('features:' . $helper->escapePhrase($input)); diff --git a/examples/6.3-demo-app.php b/examples/6.3-demo-app.php deleted file mode 100644 index e83081f48..000000000 --- a/examples/6.3-demo-app.php +++ /dev/null @@ -1,8 +0,0 @@ -createSelect(); + +// search input string, this value fails without escaping because of the double-quote +$input = 'ATA "133'; + +// the placeholder syntax applies phrase escaping to the first term +// see the manual for all supported formats +$query->setQuery('features: %p1% AND inStock:%2%',array($input,1)); + +// show the result after replacing the placeholders with values +echo $query->getQuery() . '
'; + +// this executes the query and returns the result +$resultset = $client->select($query); + +// display the total number of documents found by solr +echo 'NumFound: '.$resultset->getNumFound(); + +// show documents using the resultset iterator +foreach ($resultset as $document) { + + echo '
'; + + // the documents are also iterable, to get all fields + foreach($document AS $field => $value) + { + // this converts multivalue fields to a comma-separated string + if(is_array($value)) $value = implode(', ', $value); + + echo ''; + } + + echo '
' . $field . '' . $value . '
'; +} + +htmlFooter(); \ No newline at end of file diff --git a/examples/index.html b/examples/index.html index 5eb898081..2bd9da68d 100644 --- a/examples/index.html +++ b/examples/index.html @@ -43,6 +43,9 @@

Solarium examples

  • 2.5.2 MoreLikeThis
  • 2.5.3 Highlighting
  • 2.5.4 Dismax
  • +
  • 2.5.5 Edismax
  • +
  • 2.5.5 Grouping by field
  • +
  • 2.5.6 Grouping by query
  • 2.6 Helper functions
  • 2.7 Query re-use
  • @@ -79,7 +82,7 @@

    Solarium examples

    diff --git a/library/Solarium/Client/Request.php b/library/Solarium/Client/Request.php index de4e7f3e7..f7c81094b 100644 --- a/library/Solarium/Client/Request.php +++ b/library/Solarium/Client/Request.php @@ -210,6 +210,10 @@ public function addParam($key, $value, $overwrite = false) } $this->_params[$key][] = $value; } else { + // not all solr handlers support 0/1 as boolean values... + if($value === true) $value = 'true'; + if($value === false) $value = 'false'; + $this->_params[$key] = $value; } } diff --git a/library/Solarium/Client/RequestBuilder/Select/Component/DisMax.php b/library/Solarium/Client/RequestBuilder/Select/Component/DisMax.php index a00119fe5..4c9ded9fd 100644 --- a/library/Solarium/Client/RequestBuilder/Select/Component/DisMax.php +++ b/library/Solarium/Client/RequestBuilder/Select/Component/DisMax.php @@ -55,7 +55,7 @@ class Solarium_Client_RequestBuilder_Select_Component_DisMax public function build($component, $request) { // enable dismax - $request->addParam('defType', 'dismax'); + $request->addParam('defType', $component->getQueryParser()); $request->addParam('q.alt', $component->getQueryAlternative()); $request->addParam('qf', $component->getQueryFields()); diff --git a/library/Solarium/Client/RequestBuilder/Select/Component/Grouping.php b/library/Solarium/Client/RequestBuilder/Select/Component/Grouping.php new file mode 100644 index 000000000..d2e02052b --- /dev/null +++ b/library/Solarium/Client/RequestBuilder/Select/Component/Grouping.php @@ -0,0 +1,71 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Client + */ + +/** + * Add select component Grouping to the request + * + * @package Solarium + * @subpackage Client + */ +class Solarium_Client_RequestBuilder_Select_Component_Grouping +{ + + /** + * Add request settings for Grouping + * + * @param Solarium_Query_Select_Component_Grouping $component + * @param Solarium_Client_Request $request + * @return Solarium_Client_Request + */ + public function build($component, $request) + { + // enable grouping + $request->addParam('group', 'true'); + + $request->addParam('group.field', $component->getFields()); + $request->addParam('group.query', $component->getQueries()); + $request->addParam('group.limit', $component->getLimit()); + $request->addParam('group.offset', $component->getOffset()); + $request->addParam('group.sort', $component->getSort()); + $request->addParam('group.main', $component->getMainResult()); + $request->addParam('group.ngroups', $component->getNumberOfGroups()); + $request->addParam('group.cache.percent', $component->getCachePercentage()); + + return $request; + } +} \ No newline at end of file diff --git a/library/Solarium/Client/ResponseParser/Select.php b/library/Solarium/Client/ResponseParser/Select.php index 3970109bc..11c8747e5 100644 --- a/library/Solarium/Client/ResponseParser/Select.php +++ b/library/Solarium/Client/ResponseParser/Select.php @@ -76,11 +76,17 @@ public function parse($result) $components[$component->getType()] = $componentParser->parse($query, $component, $data); } } + + if (isset($data['response']['numFound'])) { + $numFound = $data['response']['numFound']; + } else { + $numFound = null; + } return array( 'status' => $data['responseHeader']['status'], 'queryTime' => $data['responseHeader']['QTime'], - 'numfound' => $data['response']['numFound'], + 'numfound' => $numFound, 'documents' => $documents, 'components' => $components, ); diff --git a/library/Solarium/Client/ResponseParser/Select/Component/Grouping.php b/library/Solarium/Client/ResponseParser/Select/Component/Grouping.php new file mode 100644 index 000000000..e93878590 --- /dev/null +++ b/library/Solarium/Client/ResponseParser/Select/Component/Grouping.php @@ -0,0 +1,121 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Client + */ + +/** + * Parse select component Grouping result from the data + * + * @package Solarium + * @subpackage Client + */ +class Solarium_Client_ResponseParser_Select_Component_Grouping +{ + + /** + * Parse result data into result objects + * + * @param Solarium_Query_Select $query + * @param Solarium_Query_Select_Component_Grouping $grouping + * @param array $data + * @return Solarium_Result_Select_Grouping + */ + public function parse($query, $grouping, $data) + { + $groups = array(); + + if (isset($data['grouped'])) { + + // parse field groups + foreach ($grouping->getFields() as $field) { + if (isset($data['grouped'][$field])) { + $result = $data['grouped'][$field]; + + $matches = (isset($result['matches'])) ? $result['matches'] : null; + $groupCount = (isset($result['ngroups'])) ? $result['ngroups'] : null; + $valueGroups = array(); + foreach ($result['groups'] as $valueGroupResult) { + + $value = (isset($valueGroupResult['groupValue'])) ? $valueGroupResult['groupValue'] : null; + $numFound = (isset($valueGroupResult['doclist']['numFound'])) ? $valueGroupResult['doclist']['numFound'] : null; + $start = (isset($valueGroupResult['doclist']['start'])) ? $valueGroupResult['doclist']['start'] : null; + + // create document instances + $documentClass = $query->getOption('documentclass'); + $documents = array(); + if (isset($valueGroupResult['doclist']['docs']) && is_array($valueGroupResult['doclist']['docs'])) { + foreach ($valueGroupResult['doclist']['docs'] as $doc) { + $documents[] = new $documentClass($doc); + } + } + + $valueGroups[] = new Solarium_Result_Select_Grouping_ValueGroup($value, $numFound, $start, $documents); + } + + $groups[$field] = new Solarium_Result_Select_Grouping_FieldGroup($matches, $groupCount, $valueGroups); + } + } + + // parse query groups + foreach ($grouping->getQueries() as $groupQuery) { + if (isset($data['grouped'][$groupQuery])) { + $result = $data['grouped'][$groupQuery]; + + // get statistics + $matches = (isset($result['matches'])) ? $result['matches'] : null; + $numFound = (isset($result['doclist']['numFound'])) ? $result['doclist']['numFound'] : null; + $start = (isset($result['doclist']['start'])) ? $result['doclist']['start'] : null; + $maxScore = (isset($result['doclist']['maxScore'])) ? $result['doclist']['maxScore'] : null; + + // create document instances + $documentClass = $query->getOption('documentclass'); + $documents = array(); + if (isset($result['doclist']['docs']) && is_array($result['doclist']['docs'])) { + foreach ($result['doclist']['docs'] as $doc) { + $documents[] = new $documentClass($doc); + } + } + + // create a group result object + $group = new Solarium_Result_Select_Grouping_QueryGroup($matches, $numFound, $start, $maxScore, $documents); + $groups[$groupQuery] = $group; + } + } + } + + return new Solarium_Result_Select_Grouping($groups); + } +} \ No newline at end of file diff --git a/library/Solarium/Document/ReadWrite.php b/library/Solarium/Document/ReadWrite.php index 7bf900090..ceb257495 100644 --- a/library/Solarium/Document/ReadWrite.php +++ b/library/Solarium/Document/ReadWrite.php @@ -75,6 +75,7 @@ class Solarium_Document_ReadWrite extends Solarium_Document_ReadOnly * Constructor * * @param array $fields + * @param array $boosts */ public function __construct($fields = array(), $boosts = array()) { diff --git a/library/Solarium/Query/Helper.php b/library/Solarium/Query/Helper.php index 7d49c6b0e..160f16b2e 100644 --- a/library/Solarium/Query/Helper.php +++ b/library/Solarium/Query/Helper.php @@ -47,6 +47,20 @@ class Solarium_Query_Helper { + /** + * Placeholder pattern for use in the assemble method + * + * @var string + */ + protected $_placeHolderPattern = '/%(L|P|T|)([0-9]+)%/i'; + + /** + * Array of parts to use for assembling a query string + * + * @var array + */ + protected $_assembleParts; + /** * Escape a term * @@ -218,4 +232,69 @@ public function functionCall($name, $params = array()) return $name . '(' . implode($params, ',') . ')'; } + /** + * Assemble a querystring with placeholders + * + * These placeholder modes are supported: + * %1% = no mode, will default to literal + * %L2% = literal + * %P3% = phrase-escaped + * %T4% = term-escaped + * + * Numbering starts at 1, so number 1 refers to the first entry + * of $parts (which has array key 0) + * You can use the same part multiple times, even in multiple modes. + * The mode letters are not case sensitive. + * + * The mode matching pattern can be customized by overriding the + * value of $this->_placeHolderPattern + * + * @since 2.1.0 + * + * @param string $query + * @param array $parts Array of strings + * @return string + */ + public function assemble($query, $parts) + { + $this->_assembleParts = $parts; + + return preg_replace_callback( + $this->_placeHolderPattern, + array($this, '_renderPlaceHolder'), + $query + ); + } + + /** + * Render placeholders in a querystring + * + * @throws Solarium_Exception + * @param array $matches + * @return string + */ + protected function _renderPlaceHolder($matches) + { + $partNumber = $matches[2]; + $partMode = strtoupper($matches[1]); + + if (isset($this->_assembleParts[$partNumber-1])) { + $value = $this->_assembleParts[$partNumber-1]; + } else { + throw new Solarium_Exception('No value supplied for part #' . $partNumber . ' in query assembler'); + } + + switch($partMode) + { + case 'P': + $value = $this->escapePhrase($value); + break; + case 'T': + $value = $this->escapeTerm($value); + break; + } + + return $value; + } + } \ No newline at end of file diff --git a/library/Solarium/Query/Select.php b/library/Solarium/Query/Select.php index acf79ef8d..dbe51fa4f 100644 --- a/library/Solarium/Query/Select.php +++ b/library/Solarium/Query/Select.php @@ -62,6 +62,7 @@ class Solarium_Query_Select extends Solarium_Query const COMPONENT_DISMAX = 'dismax'; const COMPONENT_MORELIKETHIS = 'morelikethis'; const COMPONENT_HIGHLIGHTING = 'highlighting'; + const COMPONENT_GROUPING = 'grouping'; /** * Get type for this query @@ -114,6 +115,11 @@ public function getType() 'requestbuilder' => 'Solarium_Client_RequestBuilder_Select_Component_Highlighting', 'responseparser' => 'Solarium_Client_ResponseParser_Select_Component_Highlighting', ), + self::COMPONENT_GROUPING => array( + 'component' => 'Solarium_Query_Select_Component_Grouping', + 'requestbuilder' => 'Solarium_Client_RequestBuilder_Select_Component_Grouping', + 'responseparser' => 'Solarium_Client_ResponseParser_Select_Component_Grouping', + ), ); /** @@ -188,10 +194,15 @@ protected function _init() * escaping of user input. * * @param string $query + * @param array $bind Bind values for placeholders in the query string * @return Solarium_Query_Select Provides fluent interface */ - public function setQuery($query) + public function setQuery($query, $bind = null) { + if (!is_null($bind)) { + $query = $this->getHelper()->assemble($query, $bind); + } + return $this->_setOption('query', trim($query)); } @@ -750,4 +761,16 @@ public function getHighlighting() return $this->getComponent(Solarium_Query_Select::COMPONENT_HIGHLIGHTING, true); } + /** + * Get a grouping component instance + * + * This is a convenience method that maps presets to getComponent + * + * @return Solarium_Query_Select_Component_Grouping + */ + public function getGrouping() + { + return $this->getComponent(Solarium_Query_Select::COMPONENT_GROUPING, true); + } + } \ No newline at end of file diff --git a/library/Solarium/Query/Select/Component/DisMax.php b/library/Solarium/Query/Select/Component/DisMax.php index 27dc0b17a..49a37722e 100644 --- a/library/Solarium/Query/Select/Component/DisMax.php +++ b/library/Solarium/Query/Select/Component/DisMax.php @@ -54,6 +54,15 @@ class Solarium_Query_Select_Component_DisMax extends Solarium_Query_Select_Compo */ protected $_type = Solarium_Query_Select::COMPONENT_DISMAX; + /** + * Default options + * + * @var array + */ + protected $_options = array( + 'queryparser' => 'dismax', + ); + /** * Set QueryAlternative option * @@ -276,4 +285,31 @@ public function getBoostFunctions() return $this->getOption('boostfunctions'); } + /** + * Set QueryParser option + * + * Can be used to enable edismax + * + * @since 2.1.0 + * + * @param string $parser + * @return Solarium_Query_Select_Component_DisMax Provides fluent interface + */ + public function setQueryParser($parser) + { + return $this->_setOption('queryparser', $parser); + } + + /** + * Get QueryParser option + * + * @since 2.1.0 + * + * @return string + */ + public function getQueryParser() + { + return $this->getOption('queryparser'); + } + } \ No newline at end of file diff --git a/library/Solarium/Query/Select/Component/Facet/Query.php b/library/Solarium/Query/Select/Component/Facet/Query.php index eeaf9928f..9812acad6 100644 --- a/library/Solarium/Query/Select/Component/Facet/Query.php +++ b/library/Solarium/Query/Select/Component/Facet/Query.php @@ -72,10 +72,16 @@ public function getType() * This overwrites the current value * * @param string $query + * @param array $bind Bind values for placeholders in the query string * @return Solarium_Query_Select_Facet_Query Provides fluent interface */ - public function setQuery($query) + public function setQuery($query, $bind = null) { + if (!is_null($bind)) { + $helper = new Solarium_Query_Helper; + $query = $helper->assemble($query, $bind); + } + return $this->_setOption('query', $query); } diff --git a/library/Solarium/Query/Select/Component/Grouping.php b/library/Solarium/Query/Select/Component/Grouping.php new file mode 100644 index 000000000..5f2a14fb9 --- /dev/null +++ b/library/Solarium/Query/Select/Component/Grouping.php @@ -0,0 +1,381 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Query + */ + +/** + * Grouping component + * + * Also known as Result Grouping or Field Collapsing. + * See the Solr wiki for more info about this functionality + * + * @link http://wiki.apache.org/solr/FieldCollapsing + * + * @since 2.1.0 + * + * @package Solarium + * @subpackage Query + */ +class Solarium_Query_Select_Component_Grouping extends Solarium_Query_Select_Component +{ + + /** + * Values for format option + */ + const FORMAT_GROUPED = 'grouped'; + const FORMAT_SIMPLE = 'simple'; + + /** + * Component type + * + * @var string + */ + protected $_type = Solarium_Query_Select::COMPONENT_GROUPING; + + /** + * Fields for grouping + * + * @var array + */ + protected $_fields = array(); + + /** + * Queries for grouping + * + * @var array + */ + protected $_queries = array(); + + /** + * Initialize options + * + * Several options need some extra checks or setup work, for these options + * the setters are called. + * + * @return void + */ + protected function _init() + { + foreach ($this->_options AS $name => $value) { + switch ($name) { + case 'queries': + $this->setQueries($value); + break; + case 'fields': + $this->setFields($value); + break; + } + } + } + + /** + * Add a grouping field + * + * Group based on the unique values of a field + * + * @param string $field + * @return Solarium_Field_Select_Component_Grouping fluent interface + */ + public function addField($field) + { + $this->_fields[] = $field; + + return $this; + } + + /** + * Add multiple grouping fields + * + * You can use an array or a comma separated string as input + * + * @param array|string $fields + * @return Solarium_Field_Select_Component_Grouping Provides fluent interface + */ + public function addFields($fields) + { + if (is_string($fields)) { + $fields = explode(',', $fields); + $fields = array_map('trim', $fields); + } + + $this->_fields = array_merge($this->_fields, $fields); + + return $this; + } + + /** + * Get all fields + * + * @return array + */ + public function getFields() + { + return $this->_fields; + } + + /** + * Remove all fields + * + * @return Solarium_Field_Select_Component_Grouping fluent interface + */ + public function clearFields() + { + $this->_fields = array(); + return $this; + } + + /** + * Set multiple fields + * + * This overwrites any existing fields + * + * @param array $fields + */ + public function setFields($fields) + { + $this->clearFields(); + $this->addFields($fields); + } + + /** + * Add a grouping query + * + * Group documents that match the given query + * + * @param string $query + * @return Solarium_Query_Select_Component_Grouping fluent interface + */ + public function addQuery($query) + { + $this->_queries[] = $query; + + return $this; + } + + /** + * Add multiple grouping queries + * + * @param array|string $queries + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function addQueries($queries) + { + if(!is_array($queries)) $queries = array($queries); + + $this->_queries = array_merge($this->_queries, $queries); + + return $this; + } + + /** + * Get all queries + * + * @return array + */ + public function getQueries() + { + return $this->_queries; + } + + /** + * Remove all queries + * + * @return Solarium_Query_Select_Component_Grouping fluent interface + */ + public function clearQueries() + { + $this->_queries = array(); + return $this; + } + + /** + * Set multiple queries + * + * This overwrites any existing queries + * + * @param array $queries + */ + public function setQueries($queries) + { + $this->clearQueries(); + $this->addQueries($queries); + } + + /** + * Set limit option + * + * The number of results (documents) to return for each group + * + * @param int $limit + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function setLimit($limit) + { + return $this->_setOption('limit', $limit); + } + + /** + * Get limit option + * + * @return string|null + */ + public function getLimit() + { + return $this->getOption('limit'); + } + + /** + * Set offset option + * + * The offset into the document list of each group. + * + * @param int $offset + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function setOffset($offset) + { + return $this->_setOption('offset', $offset); + } + + /** + * Get offset option + * + * @return string|null + */ + public function getOffset() + { + return $this->getOption('offset'); + } + + /** + * Set sort option + * + * How to sort documents within a single group + * + * @param string $sort + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function setSort($sort) + { + return $this->_setOption('sort', $sort); + } + + /** + * Get sort option + * + * @return string|null + */ + public function getSort() + { + return $this->getOption('sort'); + } + + /** + * Set mainresult option + * + * If true, the result of the first field grouping command is used as the main + * result list in the response, using group format 'simple' + * + * @param boolean $value + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function setMainResult($value) + { + return $this->_setOption('mainresult', $value); + } + + /** + * Get mainresult option + * + * @return boolean|null + */ + public function getMainResult() + { + return $this->getOption('mainresult'); + } + + /** + * Set numberofgroups option + * + * If true, includes the number of groups that have matched the query. + * + * @param boolean $value + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function setNumberOfGroups($value) + { + return $this->_setOption('numberofgroups', $value); + } + + /** + * Get numberofgroups option + * + * @return boolean|null + */ + public function getNumberOfGroups() + { + return $this->getOption('numberofgroups'); + } + + /** + * Set cachepercentage option + * + * If > 0 enables grouping cache. Grouping is executed actual two searches. + * This option caches the second search. A value of 0 disables grouping caching. + * + * Tests have shown that this cache only improves search time with boolean queries, + * wildcard queries and fuzzy queries. For simple queries like a term query or + * a match all query this cache has a negative impact on performance + * + * @param integer $value + * @return Solarium_Query_Select_Component_Grouping Provides fluent interface + */ + public function setCachePercentage($value) + { + return $this->_setOption('cachepercentage', $value); + } + + /** + * Get cachepercentage option + * + * @return integer|null + */ + public function getCachePercentage() + { + return $this->getOption('cachepercentage'); + } + +} \ No newline at end of file diff --git a/library/Solarium/Query/Select/FilterQuery.php b/library/Solarium/Query/Select/FilterQuery.php index d396351ff..b9c5f3fd9 100644 --- a/library/Solarium/Query/Select/FilterQuery.php +++ b/library/Solarium/Query/Select/FilterQuery.php @@ -111,10 +111,16 @@ public function setKey($value) * This overwrites the current value * * @param string $query + * @param array $bind Bind values for placeholders in the query string * @return Solarium_Query Provides fluent interface */ - public function setQuery($query) + public function setQuery($query, $bind = null) { + if (!is_null($bind)) { + $helper = new Solarium_Query_Helper; + $query = $helper->assemble($query, $bind); + } + $this->_query = trim($query); return $this; } diff --git a/library/Solarium/Query/Update.php b/library/Solarium/Query/Update.php index 97ae83d13..ac42c55de 100644 --- a/library/Solarium/Query/Update.php +++ b/library/Solarium/Query/Update.php @@ -79,6 +79,7 @@ class Solarium_Query_Update extends Solarium_Query protected $_options = array( 'handler' => 'update', 'resultclass' => 'Solarium_Result_Update', + 'documentclass' => 'Solarium_Document_ReadWrite', ); /** @@ -359,4 +360,49 @@ public function addOptimize($waitFlush = null, $waitSearcher = null, return $this->add(null, $optimize); } + /** + * Set a custom document class for use in the createDocument method + * + * This class should extend Solarium_Document_ReadWrite or + * at least be compatible with it's interface + * + * @param string $value classname + * @return Solarium_Query + */ + public function setDocumentClass($value) + { + return $this->_setOption('documentclass', $value); + } + + /** + * Get the current documentclass option + * + * The value is a classname, not an instance + * + * @return string + */ + public function getDocumentClass() + { + return $this->getOption('documentclass'); + } + + /** + * Create a document object instance + * + * You can optionally directly supply the fields and boosts + * to get a ready-made document instance for direct use in an add command + * + * @since 2.1.0 + * + * @param array $fields + * @param array $boosts + * @return Solarium_Document_ReadWrite + */ + public function createDocument($fields = array(), $boosts = array()) + { + $class = $this->getDocumentClass(); + + return new $class($fields, $boosts); + } + } \ No newline at end of file diff --git a/library/Solarium/Result/Select.php b/library/Solarium/Result/Select.php index 3e9ba9b18..7d9c609f7 100644 --- a/library/Solarium/Result/Select.php +++ b/library/Solarium/Result/Select.php @@ -234,6 +234,18 @@ public function getHighlighting() return $this->getComponent(Solarium_Query_Select::COMPONENT_HIGHLIGHTING); } + /** + * Get grouping component result + * + * This is a convenience method that maps presets to getComponent + * + * @return Solarium_Result_Select_Grouping + */ + public function getGrouping() + { + return $this->getComponent(Solarium_Query_Select::COMPONENT_GROUPING); + } + /** * Get facetset component result * diff --git a/library/Solarium/Result/Select/Grouping.php b/library/Solarium/Result/Select/Grouping.php new file mode 100644 index 000000000..49f89e1a7 --- /dev/null +++ b/library/Solarium/Result/Select/Grouping.php @@ -0,0 +1,112 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Result + */ + +/** + * Select component grouping result + * + * @since 2.1.0 + * + * @package Solarium + * @subpackage Result + */ +class Solarium_Result_Select_Grouping implements IteratorAggregate, Countable +{ + + /** + * Group results array + * + * @var array + */ + protected $_groups; + + /** + * Constructor + * + * @param array $groups + * @return void + */ + public function __construct($groups) + { + $this->_groups = $groups; + } + + /** + * Get all groups + * + * @return array + */ + public function getGroups() + { + return $this->_groups; + } + + /** + * Get a group + * + * @param string $key + * @return Solarium_Result_Select_Grouping_FieldGroup|Solarium_Result_Select_Grouping_QueryGroup + */ + public function getGroup($key) + { + if (isset($this->_groups[$key])) { + return $this->_groups[$key]; + } else { + return null; + } + } + + /** + * IteratorAggregate implementation + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_groups); + } + + /** + * Countable implementation + * + * @return int + */ + public function count() + { + return count($this->_groups); + } +} \ No newline at end of file diff --git a/library/Solarium/Result/Select/Grouping/FieldGroup.php b/library/Solarium/Result/Select/Grouping/FieldGroup.php new file mode 100644 index 000000000..c64a683ca --- /dev/null +++ b/library/Solarium/Result/Select/Grouping/FieldGroup.php @@ -0,0 +1,137 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Result + */ + +/** + * Select component grouping field group result + * + * @since 2.1.0 + * + * @package Solarium + * @subpackage Result + */ +class Solarium_Result_Select_Grouping_FieldGroup implements IteratorAggregate, Countable +{ + + /** + * Match count + * + * @var int + */ + protected $_matches; + + /** + * Number of groups + * + * @var int + */ + protected $_numberOfGroups; + + /** + * Value groups + * + * @var array + */ + protected $_valueGroups; + + /** + * Constructor + * + * @param int $matches + * @param int $numberOfGroups + * @param array $groups + * @return void + */ + public function __construct($matches, $numberOfGroups, $groups) + { + $this->_matches = $matches; + $this->_numberOfGroups = $numberOfGroups; + $this->_valueGroups = $groups; + } + + /** + * Get matches value + * + * @return int + */ + public function getMatches() + { + return $this->_matches; + } + + /** + * Get numberOfGroups value + * + * Only available if the numberofgroups option in the query was 'true' + * + * @return int + */ + public function getNumberOfGroups() + { + return $this->_numberOfGroups; + } + + /** + * Get all value groups + * + * @return array + */ + public function getValueGroups() + { + return $this->_valueGroups; + } + + /** + * IteratorAggregate implementation + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_valueGroups); + } + + /** + * Countable implementation + * + * @return int + */ + public function count() + { + return count($this->_valueGroups); + } +} \ No newline at end of file diff --git a/library/Solarium/Result/Select/Grouping/QueryGroup.php b/library/Solarium/Result/Select/Grouping/QueryGroup.php new file mode 100644 index 000000000..d37d78b99 --- /dev/null +++ b/library/Solarium/Result/Select/Grouping/QueryGroup.php @@ -0,0 +1,169 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Result + */ + +/** + * Select component grouping query group result + * + * @since 2.1.0 + * + * @package Solarium + * @subpackage Result + */ +class Solarium_Result_Select_Grouping_QueryGroup implements IteratorAggregate, Countable +{ + + /** + * Match count + * + * @var int + */ + protected $_matches; + + /** + * NumFound value + * + * @var int + */ + protected $_numFound; + + /** + * Start offset + * + * @var int + */ + protected $_start; + + /** + * Maximum score in group + * + * @var float + */ + protected $_maximumScore; + + /** + * Group documents array + * + * @var array + */ + protected $_documents; + + /** + * Constructor + * + * @param array $groups + * @return void + */ + public function __construct($matches, $numFound, $start, $maximumScore, $documents) + { + $this->_matches = $matches; + $this->_numFound = $numFound; + $this->_start = $start; + $this->_maximumScore = $maximumScore; + $this->_documents = $documents; + } + + /** + * Get matches value + * + * @return int + */ + public function getMatches() + { + return $this->_matches; + } + + /** + * Get numFound value + * + * @return int + */ + public function getNumFound() + { + return $this->_numFound; + } + + /** + * Get start value + * + * @return int + */ + public function getStart() + { + return $this->_start; + } + + /** + * Get maximumScore value + * + * @return int + */ + public function getMaximumScore() + { + return $this->_maximumScore; + } + + /** + * Get all documents + * + * @return array + */ + public function getDocuments() + { + return $this->_documents; + } + + /** + * IteratorAggregate implementation + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_documents); + } + + /** + * Countable implementation + * + * @return int + */ + public function count() + { + return count($this->_documents); + } +} \ No newline at end of file diff --git a/library/Solarium/Result/Select/Grouping/ValueGroup.php b/library/Solarium/Result/Select/Grouping/ValueGroup.php new file mode 100644 index 000000000..1ce6f9b2c --- /dev/null +++ b/library/Solarium/Result/Select/Grouping/ValueGroup.php @@ -0,0 +1,154 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * @link http://www.solarium-project.org/ + * + * @package Solarium + * @subpackage Result + */ + +/** + * Select component grouping field value group result + * + * @since 2.1.0 + * + * @package Solarium + * @subpackage Result + */ +class Solarium_Result_Select_Grouping_ValueGroup implements IteratorAggregate, Countable +{ + + /** + * Field value + * + * @var string + */ + protected $_value; + + /** + * NumFound + * + * @var int + */ + protected $_numFound; + + /** + * Start position + * + * @var int + */ + protected $_start; + + /** + * Documents in this group + * + * @var array + */ + protected $_documents; + + /** + * Constructor + * + * @param string $value + * @param int $numFound + * @param int $start + * @param array $documents + * @return void + */ + public function __construct($value, $numFound, $start, $documents) + { + $this->_value = $value; + $this->_numFound = $numFound; + $this->_start = $start; + $this->_documents = $documents; + } + + /** + * Get value + * + * @return string + */ + public function getValue() + { + return $this->_value; + } + + /** + * Get numFound + * + * @return int + */ + public function getNumFound() + { + return $this->_numFound; + } + + /** + * Get start + * + * @return int + */ + public function getStart() + { + return $this->_start; + } + + /** + * Get all documents + * + * @return array + */ + public function getDocuments() + { + return $this->_documents; + } + + /** + * IteratorAggregate implementation + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_documents); + } + + /** + * Countable implementation + * + * @return int + */ + public function count() + { + return count($this->_documents); + } +} \ No newline at end of file diff --git a/tests/Solarium/Client/RequestBuilder/Select/Component/DisMaxTest.php b/tests/Solarium/Client/RequestBuilder/Select/Component/DisMaxTest.php index a2cec030b..b7511c276 100644 --- a/tests/Solarium/Client/RequestBuilder/Select/Component/DisMaxTest.php +++ b/tests/Solarium/Client/RequestBuilder/Select/Component/DisMaxTest.php @@ -38,6 +38,7 @@ public function testBuild() $request = new Solarium_Client_Request(); $component = new Solarium_Query_Select_Component_DisMax(); + $component->setQueryParser('dummyparser'); $component->setQueryAlternative('test'); $component->setQueryFields('content,name'); $component->setMinimumMatch('75%'); @@ -52,7 +53,7 @@ public function testBuild() $this->assertEquals( array( - 'defType' => 'dismax', + 'defType' => 'dummyparser', 'q.alt' => 'test', 'qf' => 'content,name', 'mm' => '75%', diff --git a/tests/Solarium/Client/RequestBuilder/Select/Component/FacetSetTest.php b/tests/Solarium/Client/RequestBuilder/Select/Component/FacetSetTest.php index 747bf0c29..d010420a1 100644 --- a/tests/Solarium/Client/RequestBuilder/Select/Component/FacetSetTest.php +++ b/tests/Solarium/Client/RequestBuilder/Select/Component/FacetSetTest.php @@ -126,7 +126,7 @@ public function testBuildWithFacetsAndGlobalFacetSettings() ); $this->assertEquals( - '?facet=true&facet.missing=1&facet.limit=10&facet.field={!key=f1}owner&facet.query={!key=f2}category:23&facet.query={!key=f4}category:40', + '?facet=true&facet.missing=true&facet.limit=10&facet.field={!key=f1}owner&facet.query={!key=f2}category:23&facet.query={!key=f4}category:40', urldecode($request->getUri()) ); } diff --git a/tests/Solarium/Client/RequestBuilder/Select/Component/GroupingTest.php b/tests/Solarium/Client/RequestBuilder/Select/Component/GroupingTest.php new file mode 100644 index 000000000..0924a8cb6 --- /dev/null +++ b/tests/Solarium/Client/RequestBuilder/Select/Component/GroupingTest.php @@ -0,0 +1,69 @@ +setFields(array('fieldA','fieldB')); + $component->setQueries(array('cat:1','cat:2')); + $component->setLimit(12); + $component->setOffset(2); + $component->setSort('score desc'); + $component->setMainResult(true); + $component->setNumberOfGroups(false); + $component->setCachePercentage(50); + + $request = $builder->build($component, $request); + + $this->assertEquals( + array( + 'group' => 'true', + 'group.field' => array('fieldA','fieldB'), + 'group.query' => array('cat:1','cat:2'), + 'group.limit' => 12, + 'group.offset' => 2, + 'group.sort' => 'score desc', + 'group.main' => 'true', + 'group.ngroups' => 'false', + 'group.cache.percent' => 50, + ), + $request->getParams() + ); + + } + +} diff --git a/tests/Solarium/Client/RequestBuilder/Select/Component/HighlightingTest.php b/tests/Solarium/Client/RequestBuilder/Select/Component/HighlightingTest.php index 27695b7f2..83197c23c 100644 --- a/tests/Solarium/Client/RequestBuilder/Select/Component/HighlightingTest.php +++ b/tests/Solarium/Client/RequestBuilder/Select/Component/HighlightingTest.php @@ -63,12 +63,12 @@ public function testBuild() $this->assertEquals( array( - 'hl' => true, + 'hl' => 'true', 'hl.fl' => 'fieldA,fieldB', 'hl.snippets' => 2, 'hl.fragsize' => 3, - 'hl.mergeContiguous' => true, - 'hl.requireFieldMatch' => false, + 'hl.mergeContiguous' => 'true', + 'hl.requireFieldMatch' => 'false', 'hl.maxAnalyzedChars' => 100, 'hl.alternateField' => 'fieldC', 'hl.maxAlternateFieldLength' => 5, @@ -78,9 +78,9 @@ public function testBuild() 'hl.fragmenter' => 'myFragmenter', 'hl.fragListBuilder' => 'myFragListBuilder', 'hl.fragmentsBuilder' => 'myFragmentsBuilder', - 'hl.useFastVectorHighlighter' => false, - 'hl.usePhraseHighlighter' => true, - 'hl.highlightMultiTerm' => true, + 'hl.useFastVectorHighlighter' => 'false', + 'hl.usePhraseHighlighter' => 'true', + 'hl.highlightMultiTerm' => 'true', 'hl.regex.slop' => 1.3, 'hl.regex.pattern' => 'mypattern', ), diff --git a/tests/Solarium/Client/RequestTest.php b/tests/Solarium/Client/RequestTest.php index d72bb332b..1f65b879c 100644 --- a/tests/Solarium/Client/RequestTest.php +++ b/tests/Solarium/Client/RequestTest.php @@ -172,6 +172,24 @@ public function testAddParam() ); } + public function testAddParamBoolean() + { + $params = array( + 'param1' => true, + 'param2' => false, + ); + + $this->_request->addParams($params); + + $this->assertEquals( + array( + 'param1' => 'true', + 'param2' => 'false', + ), + $this->_request->getParams() + ); + } + public function testAddParamMultivalue() { $params = array( diff --git a/tests/Solarium/Client/ResponseParser/Select/Component/GroupingTest.php b/tests/Solarium/Client/ResponseParser/Select/Component/GroupingTest.php new file mode 100644 index 000000000..f41b82b5c --- /dev/null +++ b/tests/Solarium/Client/ResponseParser/Select/Component/GroupingTest.php @@ -0,0 +1,139 @@ +_parser = new Solarium_Client_ResponseParser_Select_Component_Grouping; + $this->_query = new Solarium_Query_Select(); + $this->_grouping = $this->_query->getGrouping(); + $this->_grouping->addField('fieldA'); + $this->_grouping->addQuery('cat:1'); + + $data = array( + 'grouped' => array( + 'fieldA' => array( + 'matches' => 25, + 'ngroups' => 12, + 'groups' => array( + array( + 'groupValue' => 'test value', + 'doclist' => array( + 'numFound' => 13, + 'docs' => array( + array('id' => 1, 'name' => 'test') + ) + ) + ) + ) + ), + 'cat:1' => array( + 'matches' => 40, + 'doclist' => array( + 'numFound' => 22, + 'docs' => array( + array('id' => 2, 'name' => 'dummy2'), + array('id' => 5, 'name' => 'dummy5') + ) + ) + ) + ) + ); + + $this->_result = $this->_parser->parse($this->_query, $this->_grouping, $data); + } + + public function testGroupParsing() + { + $this->assertEquals(2, count($this->_result->getGroups())); + + $fieldGroup = $this->_result->getGroup('fieldA'); + $queryGroup = $this->_result->getGroup('cat:1'); + + $this->assertEquals('Solarium_Result_Select_Grouping_FieldGroup', get_class($fieldGroup)); + $this->assertEquals('Solarium_Result_Select_Grouping_QueryGroup', get_class($queryGroup)); + } + + public function testFieldGroupParsing() + { + $fieldGroup = $this->_result->getGroup('fieldA'); + $valueGroups = $fieldGroup->getValueGroups(); + + $this->assertEquals(25, $fieldGroup->getMatches()); + $this->assertEquals(12, $fieldGroup->getNumberOfGroups()); + $this->assertEquals(1, count($valueGroups)); + + $valueGroup = $valueGroups[0]; + $this->assertEquals(13, $valueGroup->getNumFound()); + + $docs = $valueGroup->getDocuments(); + $this->assertEquals('test', $docs[0]->name); + } + + public function testQueryGroupParsing() + { + $queryGroup = $this->_result->getGroup('cat:1'); + + $this->assertEquals(40, $queryGroup->getMatches()); + $this->assertEquals(22, $queryGroup->getNumFound()); + + $docs = $queryGroup->getDocuments(); + $this->assertEquals('dummy5', $docs[1]->name); + } + + public function testParseNoData() + { + $result = $this->_parser->parse($this->_query, $this->_grouping, array()); + $this->assertEquals(array(), $result->getGroups()); + } +} diff --git a/tests/Solarium/Client/ResponseParser/SelectTest.php b/tests/Solarium/Client/ResponseParser/SelectTest.php index 7ca8ff073..6296c1ec0 100644 --- a/tests/Solarium/Client/ResponseParser/SelectTest.php +++ b/tests/Solarium/Client/ResponseParser/SelectTest.php @@ -76,8 +76,40 @@ public function testParse() Solarium_Query_Select::COMPONENT_FACETSET => new Solarium_Result_Select_FacetSet(array()) ); $this->assertEquals($components, $result['components']); + } + + public function testParseWithoutNumFound() + { + $data = array( + 'response' => array( + 'docs' => array( + array('fieldA' => 1, 'fieldB' => 'Test'), + array('fieldA' => 2, 'fieldB' => 'Test2') + ), + ), + 'responseHeader' => array( + 'status' => 1, + 'QTime' => 13, + ) + ); + $query = new Solarium_Query_Select(array('documentclass' => 'Solarium_Document_ReadWrite')); + $query->getFacetSet(); + $resultStub = $this->getMock('Solarium_Result_Select', array(), array(), '', false); + $resultStub->expects($this->once()) + ->method('getData') + ->will($this->returnValue($data)); + $resultStub->expects($this->once()) + ->method('getQuery') + ->will($this->returnValue($query)); + + $parser = new Solarium_Client_ResponseParser_Select; + $result = $parser->parse($resultStub); + + $this->assertEquals(1, $result['status']); + $this->assertEquals(13, $result['queryTime']); + $this->assertEquals(null, $result['numfound']); } } diff --git a/tests/Solarium/Query/HelperTest.php b/tests/Solarium/Query/HelperTest.php index dcf8aaf9b..b84212c45 100644 --- a/tests/Solarium/Query/HelperTest.php +++ b/tests/Solarium/Query/HelperTest.php @@ -152,4 +152,49 @@ public function testEscapePhraseNoEscape() ); } + public function testAssemble() + { + // test single basic placeholder + $this->assertEquals( + 'id:456 AND cat:2', + $this->_helper->assemble('id:%1% AND cat:2',array(456)) + ); + + // test multiple basic placeholders and placeholder repeat + $this->assertEquals( + '(id:456 AND cat:2) OR (id:456 AND cat:1)', + $this->_helper->assemble('(id:%1% AND cat:%2%) OR (id:%1% AND cat:%3%)',array(456, 2, 1)) + ); + + // test literal placeholder (same as basic) + $this->assertEquals( + 'id:456 AND cat:2', + $this->_helper->assemble('id:%L1% AND cat:2',array(456)) + ); + + // test term placeholder + $this->assertEquals( + 'cat:2 AND content:a\\+b', + $this->_helper->assemble('cat:2 AND content:%T1%',array('a+b')) + ); + + // test term placeholder case-insensitive + $this->assertEquals( + 'cat:2 AND content:a\\+b', + $this->_helper->assemble('cat:2 AND content:%t1%',array('a+b')) + ); + + // test phrase placeholder + $this->assertEquals( + 'cat:2 AND content:"a+\\"b"', + $this->_helper->assemble('cat:2 AND content:%P1%',array('a+"b')) + ); + } + + public function testAssembleInvalidPartNumber() + { + $this->setExpectedException('Solarium_Exception'); + $this->_helper->assemble('cat:%1% AND content:%2%',array('value1')); + } + } diff --git a/tests/Solarium/Query/Select/Component/DisMaxTest.php b/tests/Solarium/Query/Select/Component/DisMaxTest.php index cbc863357..12973cf51 100644 --- a/tests/Solarium/Query/Select/Component/DisMaxTest.php +++ b/tests/Solarium/Query/Select/Component/DisMaxTest.php @@ -45,6 +45,7 @@ public function setUp() public function testConfigMode() { $options = array( + 'queryparser' => 'edismax', 'queryalternative' => '*:*', 'queryfields' => 'title^2.0 description', 'minimummatch' => '2.0', @@ -58,6 +59,7 @@ public function testConfigMode() $this->_disMax->setOptions($options); + $this->assertEquals($options['queryparser'], $this->_disMax->getQueryParser()); $this->assertEquals($options['queryalternative'], $this->_disMax->getQueryAlternative()); $this->assertEquals($options['queryfields'], $this->_disMax->getQueryFields()); $this->assertEquals($options['minimummatch'], $this->_disMax->getMinimumMatch()); @@ -77,6 +79,17 @@ public function testGetType() ); } + public function testSetAndGetQueryParser() + { + $value = 'dummyparser'; + $this->_disMax->setQueryParser($value); + + $this->assertEquals( + $value, + $this->_disMax->getQueryParser() + ); + } + public function testSetAndGetQueryAlternative() { $value = '*:*'; diff --git a/tests/Solarium/Query/Select/Component/Facet/QueryTest.php b/tests/Solarium/Query/Select/Component/Facet/QueryTest.php index 01e1e2422..f48ba576e 100644 --- a/tests/Solarium/Query/Select/Component/Facet/QueryTest.php +++ b/tests/Solarium/Query/Select/Component/Facet/QueryTest.php @@ -71,5 +71,9 @@ public function testSetAndGetQuery() $this->assertEquals('category:1', $this->_facet->getQuery()); } - + public function testSetAndGetQueryWithBind() + { + $this->_facet->setQuery('id:%1%', array(678)); + $this->assertEquals('id:678', $this->_facet->getQuery()); + } } diff --git a/tests/Solarium/Query/Select/Component/GroupingTest.php b/tests/Solarium/Query/Select/Component/GroupingTest.php new file mode 100644 index 000000000..041a076c6 --- /dev/null +++ b/tests/Solarium/Query/Select/Component/GroupingTest.php @@ -0,0 +1,199 @@ +_grouping = new Solarium_Query_Select_Component_Grouping; + } + + public function testConfigMode() + { + $options = array( + 'fields' => array('fieldA','fieldB'), + 'queries' => array('cat:3','cat:4'), + 'limit' => 8, + 'offset' => 1, + 'sort' => 'score desc', + 'mainresult' => false, + 'numberofgroups' => true, + 'cachepercentage' => 45, + ); + + $this->_grouping->setOptions($options); + + $this->assertEquals($options['fields'], $this->_grouping->getFields()); + $this->assertEquals($options['queries'], $this->_grouping->getQueries()); + $this->assertEquals($options['limit'], $this->_grouping->getLimit()); + $this->assertEquals($options['offset'], $this->_grouping->getOffset()); + $this->assertEquals($options['sort'], $this->_grouping->getSort()); + $this->assertEquals($options['mainresult'], $this->_grouping->getMainResult()); + $this->assertEquals($options['numberofgroups'], $this->_grouping->getNumberOfGroups()); + $this->assertEquals($options['cachepercentage'], $this->_grouping->getCachePercentage()); + } + + public function testGetType() + { + $this->assertEquals(Solarium_Query_Select::COMPONENT_GROUPING, $this->_grouping->getType()); + } + + public function testSetAndGetFieldsSingle() + { + $value = 'fieldC'; + $this->_grouping->setFields($value); + + $this->assertEquals( + array($value), + $this->_grouping->getFields() + ); + } + + public function testSetAndGetFieldsCommaSeparated() + { + $value = 'fieldD, fieldE'; + $this->_grouping->setFields($value); + + $this->assertEquals( + array( + 'fieldD', + 'fieldE', + ), + $this->_grouping->getFields() + ); + } + + public function testSetAndGetFieldsArray() + { + $values = array('fieldD', 'fieldE'); + $this->_grouping->setFields($values); + + $this->assertEquals( + $values, + $this->_grouping->getFields() + ); + } + + public function testSetAndGetQueriesSingle() + { + $value = 'cat:3'; + $this->_grouping->setQueries($value); + + $this->assertEquals( + array($value), + $this->_grouping->getQueries() + ); + } + + public function testSetAndGetQueriesArray() + { + $values = array('cat:5', 'cat:6'); + $this->_grouping->setQueries($values); + + $this->assertEquals( + $values, + $this->_grouping->getQueries() + ); + } + + public function testSetAndGetLimit() + { + $value = '12'; + $this->_grouping->setLimit($value); + + $this->assertEquals( + $value, + $this->_grouping->getLimit() + ); + } + + public function testSetAndGetOffset() + { + $value = '2'; + $this->_grouping->setOffset($value); + + $this->assertEquals( + $value, + $this->_grouping->getOffset() + ); + } + + public function testSetAndGetSort() + { + $value = 'price desc'; + $this->_grouping->setSort($value); + + $this->assertEquals( + $value, + $this->_grouping->getSort() + ); + } + + public function testSetAndGetMainResult() + { + $value = true; + $this->_grouping->setMainResult($value); + + $this->assertEquals( + $value, + $this->_grouping->getMainResult() + ); + } + + public function testSetAndGetNumberOfGroups() + { + $value = true; + $this->_grouping->setNumberOfGroups($value); + + $this->assertEquals( + $value, + $this->_grouping->getNumberOfGroups() + ); + } + + public function testSetAndGetCachePercentage() + { + $value = 40; + $this->_grouping->setCachePercentage($value); + + $this->assertEquals( + $value, + $this->_grouping->getCachePercentage() + ); + } + +} diff --git a/tests/Solarium/Query/Select/FilterQueryTest.php b/tests/Solarium/Query/Select/FilterQueryTest.php index b09560541..75afd0ed5 100644 --- a/tests/Solarium/Query/Select/FilterQueryTest.php +++ b/tests/Solarium/Query/Select/FilterQueryTest.php @@ -69,6 +69,12 @@ public function testSetAndGetQuery() $this->assertEquals('category:1', $this->_filterQuery->getQuery()); } + public function testSetAndGetQueryWithBind() + { + $this->_filterQuery->setQuery('id:%1%', array(678)); + $this->assertEquals('id:678', $this->_filterQuery->getQuery()); + } + public function testAddTag() { $this->_filterQuery->addTag('testtag'); diff --git a/tests/Solarium/Query/SelectTest.php b/tests/Solarium/Query/SelectTest.php index 430672e54..33c45d805 100644 --- a/tests/Solarium/Query/SelectTest.php +++ b/tests/Solarium/Query/SelectTest.php @@ -56,6 +56,12 @@ public function testSetAndGetQueryWithTrim() $this->assertEquals('*:*', $this->_query->getQuery()); } + public function testSetAndGetQueryWithBind() + { + $this->_query->setQuery('id:%1%', array(678)); + $this->assertEquals('id:678', $this->_query->getQuery()); + } + public function testSetAndGetResultClass() { $this->_query->setResultClass('MyResult'); @@ -471,11 +477,21 @@ public function testGetDisMax() public function testGetHighlighting() { - $dismax = $this->_query->getHighlighting(); + $hlt = $this->_query->getHighlighting(); $this->assertEquals( 'Solarium_Query_Select_Component_Highlighting', - get_class($dismax) + get_class($hlt) + ); + } + + public function testGetGrouping() + { + $grouping = $this->_query->getGrouping(); + + $this->assertEquals( + 'Solarium_Query_Select_Component_Grouping', + get_class($grouping) ); } diff --git a/tests/Solarium/Query/UpdateTest.php b/tests/Solarium/Query/UpdateTest.php index 1d0511d1c..167f6aa55 100644 --- a/tests/Solarium/Query/UpdateTest.php +++ b/tests/Solarium/Query/UpdateTest.php @@ -402,4 +402,48 @@ public function testCreateCommandWithInvalidQueryType() $this->_query->createCommand('invalidtype'); } + public function testSetAndGetDocumentClass() + { + $this->_query->setDocumentClass('MyDocument'); + $this->assertEquals('MyDocument', $this->_query->getDocumentClass()); + } + + public function testCreateDocument() + { + $doc = $this->_query->createDocument(); + $this->assertThat($doc, $this->isInstanceOf($this->_query->getDocumentClass())); + } + + public function testCreateDocumentWithCustomClass() + { + $this->_query->setDocumentClass('MyCustomDoc'); + + $doc = $this->_query->createDocument(); + $this->assertThat($doc, $this->isInstanceOf('MyCustomDoc')); + } + + public function testCreateDocumentWithFieldsAndBoosts() + { + $fields = array('id' => 1, 'name' => 'testname'); + $boosts = array('name' => 2.7); + + $doc = $this->_query->createDocument($fields, $boosts); + + $this->assertThat($doc, $this->isInstanceOf($this->_query->getDocumentClass())); + + $this->assertEquals( + $fields, + $doc->getFields() + ); + + $this->assertEquals( + 2.7, + $doc->getFieldBoost('name') + ); + } + +} + +class MyCustomDoc extends Solarium_Document_ReadWrite{ + } diff --git a/tests/Solarium/Result/Select/Grouping/FieldGroupTest.php b/tests/Solarium/Result/Select/Grouping/FieldGroupTest.php new file mode 100644 index 000000000..518ab5fac --- /dev/null +++ b/tests/Solarium/Result/Select/Grouping/FieldGroupTest.php @@ -0,0 +1,87 @@ +_matches = 12; + $this->_numberOfGroups = 6; + + $this->_items = array( + 'key1' => 'content1', + 'key2' => 'content2', + ); + + $this->_group = new Solarium_Result_Select_Grouping_FieldGroup($this->_matches, $this->_numberOfGroups, $this->_items); + } + + public function testGetMatches() + { + $this->assertEquals( + $this->_matches, + $this->_group->getMatches() + ); + } + + public function testGetNumberOfGroups() + { + $this->assertEquals( + $this->_numberOfGroups, + $this->_group->getNumberOfGroups() + ); + } + + public function testIterator() + { + $items = array(); + foreach($this->_group AS $key => $item) + { + $items[$key] = $item; + } + + $this->assertEquals($this->_items, $items); + } + + public function testCount() + { + $this->assertEquals(count($this->_items), count($this->_group)); + } + +} diff --git a/tests/Solarium/Result/Select/Grouping/QueryGroupTest.php b/tests/Solarium/Result/Select/Grouping/QueryGroupTest.php new file mode 100644 index 000000000..15903b1da --- /dev/null +++ b/tests/Solarium/Result/Select/Grouping/QueryGroupTest.php @@ -0,0 +1,113 @@ +_matches = 12; + $this->_numFound = 6; + $this->_start = 2; + $this->_maximumScore = 0.89; + + $this->_items = array( + 'key1' => 'content1', + 'key2' => 'content2', + ); + + $this->_group = new Solarium_Result_Select_Grouping_QueryGroup($this->_matches, $this->_numFound, $this->_start, $this->_maximumScore, $this->_items); + } + + public function testGetMatches() + { + $this->assertEquals( + $this->_matches, + $this->_group->getMatches() + ); + } + + public function testGetNumFound() + { + $this->assertEquals( + $this->_numFound, + $this->_group->getNumFound() + ); + } + + public function testGetStart() + { + $this->assertEquals( + $this->_start, + $this->_group->getStart() + ); + } + + public function testGetMaximumScore() + { + $this->assertEquals( + $this->_maximumScore, + $this->_group->getMaximumScore() + ); + } + + public function testGetDocuments() + { + $this->assertEquals( + $this->_items, + $this->_group->getDocuments() + ); + } + + public function testIterator() + { + $items = array(); + foreach($this->_group AS $key => $item) + { + $items[$key] = $item; + } + + $this->assertEquals($this->_items, $items); + } + + public function testCount() + { + $this->assertEquals(count($this->_items), count($this->_group)); + } + +} diff --git a/tests/Solarium/Result/Select/Grouping/ValueGroupTest.php b/tests/Solarium/Result/Select/Grouping/ValueGroupTest.php new file mode 100644 index 000000000..bed08c8df --- /dev/null +++ b/tests/Solarium/Result/Select/Grouping/ValueGroupTest.php @@ -0,0 +1,104 @@ +_value = 'test value'; + $this->_numFound = 6; + $this->_start = 2; + + $this->_items = array( + 'key1' => 'content1', + 'key2' => 'content2', + ); + + $this->_group = new Solarium_Result_Select_Grouping_ValueGroup($this->_value, $this->_numFound, $this->_start, $this->_items); + } + + public function testGetValue() + { + $this->assertEquals( + $this->_value, + $this->_group->getValue() + ); + } + + public function testGetNumFound() + { + $this->assertEquals( + $this->_numFound, + $this->_group->getNumFound() + ); + } + + public function testGetStart() + { + $this->assertEquals( + $this->_start, + $this->_group->getStart() + ); + } + + public function testGetDocuments() + { + $this->assertEquals( + $this->_items, + $this->_group->getDocuments() + ); + } + + public function testIterator() + { + $items = array(); + foreach($this->_group AS $key => $item) + { + $items[$key] = $item; + } + + $this->assertEquals($this->_items, $items); + } + + public function testCount() + { + $this->assertEquals(count($this->_items), count($this->_group)); + } + +} diff --git a/tests/Solarium/Result/Select/GroupingTest.php b/tests/Solarium/Result/Select/GroupingTest.php new file mode 100644 index 000000000..5d4c618c2 --- /dev/null +++ b/tests/Solarium/Result/Select/GroupingTest.php @@ -0,0 +1,92 @@ +_items = array( + 'key1' => 'content1', + 'key2' => 'content2', + ); + + $this->_grouping = new Solarium_Result_Select_Grouping($this->_items); + } + + public function testGetGroups() + { + $this->assertEquals( + $this->_items, + $this->_grouping->getGroups() + ); + } + + public function testGetGroup() + { + $this->assertEquals( + $this->_items['key1'], + $this->_grouping->getGroup('key1') + ); + } + + public function testGetGroupInvalid() + { + $this->assertEquals( + null, + $this->_grouping->getGroup('invalidkey') + ); + } + + public function testIterator() + { + $items = array(); + foreach($this->_grouping AS $key => $item) + { + $items[$key] = $item; + } + + $this->assertEquals($this->_items, $items); + } + + public function testCount() + { + $this->assertEquals(count($this->_items), count($this->_grouping)); + } + +} diff --git a/tests/Solarium/Result/SelectTest.php b/tests/Solarium/Result/SelectTest.php index 91b991d51..52c7b7752 100644 --- a/tests/Solarium/Result/SelectTest.php +++ b/tests/Solarium/Result/SelectTest.php @@ -37,7 +37,7 @@ class Solarium_Result_SelectTest extends PHPUnit_Framework_TestCase */ protected $_result; - protected $_numFound, $_docs, $_components, $_facetSet, $_moreLikeThis, $_highlighting; + protected $_numFound, $_docs, $_components, $_facetSet, $_moreLikeThis, $_highlighting, $_grouping; public function setUp() { @@ -51,11 +51,13 @@ public function setUp() $this->_facetSet = 'dummy-facetset-value'; $this->_moreLikeThis = 'dummy-facetset-value'; $this->_highlighting = 'dummy-highlighting-value'; + $this->_grouping = 'dummy-grouping-value'; $this->_components = array( Solarium_Query_Select::COMPONENT_FACETSET => $this->_facetSet, Solarium_Query_Select::COMPONENT_MORELIKETHIS => $this->_moreLikeThis, - Solarium_Query_Select::COMPONENT_HIGHLIGHTING => $this->_highlighting + Solarium_Query_Select::COMPONENT_HIGHLIGHTING => $this->_highlighting, + Solarium_Query_Select::COMPONENT_GROUPING => $this->_grouping ); $this->_result = new Solarium_Result_SelectDummy(1, 12, $this->_numFound, $this->_docs, $this->_components); @@ -118,6 +120,14 @@ public function testGetHighlighting() ); } + public function testGetGrouping() + { + $this->assertEquals( + $this->_components[Solarium_Query_Select::COMPONENT_GROUPING], + $this->_result->getGrouping() + ); + } + public function testIterator() { $docs = array();