Skip to content

Commit

Permalink
Added "searching for xxxx insted" notice
Browse files Browse the repository at this point in the history
Improved "did you mean" to use native search notice.
Extended Self Test with Autocomplete and Suggest
Search results are saved in registry as a JeroenVermeulen_Solarium_Model_SearchResult object.
  • Loading branch information
jeroenvermeulen committed Jul 18, 2014
1 parent 3be16ff commit b308b60
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 84 deletions.
44 changes: 27 additions & 17 deletions app/code/community/JeroenVermeulen/Solarium/Model/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,21 +485,23 @@ function getDocumentCount(
/**
* Query the Solr server to search for a string.
*
* @param int $storeId - Store View Id
* @param int $storeId - Store View Id
* @param string $queryString - Text to search for
* @param int $try - Times tried to find result
* @return array
* @param int $try - Times tried to find result
* @return JeroenVermeulen_Solarium_Model_SearchResult
*/
public
function search(
$storeId,
$queryString,
$try = 1
) {
$result = Mage::getModel('jeroenvermeulen_solarium/searchResult');
$result->setStoreId( $storeId );
$result->setUserQuery( $queryString );
if (!$this->_working) {
return false;
return $result;
}
$result = false;
try {
$query = $this->_client->createSelect();
$queryHelper = $query->getHelper();
Expand Down Expand Up @@ -535,16 +537,17 @@ function search(
$solrResultSet = $this->_client->select( $query );

$this->_lastQueryTime = $solrResultSet->getQueryTime();
$result = array();
$resultProducts = array();
foreach ($solrResultSet->getGrouping()->getGroup( 'product_id' ) as $valueGroup) {
foreach ($valueGroup as $solrResult) {
$key = 'prd' . $solrResult[ 'product_id' ];
$result[ $key ] = array(
$resultProducts[ $key ] = array(
'relevance' => $solrResult[ 'score' ],
'product_id' => $solrResult[ 'product_id' ]
);
}
}
$result->setResultProducts( $resultProducts );
if ($doAutoCorrect || $doDidYouMean) {
$suggest = array();
$spellCheckResult = $solrResultSet->getSpellcheck();
Expand All @@ -558,16 +561,18 @@ function search(
}
}
arsort( $suggest, SORT_NUMERIC );
if ($doAutoCorrect && empty( $result ) && !empty( $suggest )) {
if ($doAutoCorrect && empty( $resultProducts ) && !empty( $suggest )) {
$suggestKeys = array_keys( $suggest );
$bestMatch = reset( $suggestKeys );
array_shift( $suggest );
$result = $this->search( $storeId, $bestMatch, $try + 1 );
$secondSearch = $this->search( $storeId, $bestMatch, $try + 1 );
$result->setResultQuery( $bestMatch );
$result->setResultProducts( $secondSearch->getResultProducts() );
}
$suggest =
array_slice( $suggest, 0, $this->getConf( 'results/did_you_mean_suggestions', $storeId ) );
if ($doDidYouMean) {
Mage::register( 'solarium_suggest', $suggest );
$result->setSuggestions( $suggest );
}
}
}
Expand All @@ -579,15 +584,16 @@ function search(
}

/**
* @param integer $storeId - Store View Id
* @param integer $storeId - Store View Id
* @param string $queryString - What the user is typing
* @return null|string
* @return array - key = suggested term, value = result count
*/
public
function getAutoSuggestions(
$storeId,
$queryString
) {
$result = null;
// Create basic query with wildcard
$query = $this->_client->createSelect();
$queryHelper = $query->getHelper();
Expand All @@ -608,19 +614,23 @@ function getAutoSuggestions(

// Add facet for completion
$facetSet = $query->getFacetSet();
$facetField = $facetSet->createFacetField( 'text' );
$facetField = $facetSet->createFacetField( 'auto_complete' );
$facetField->setField( 'text' );
$facetField->setMincount( 1 );
$facetField->setLimit( $this->getConf( 'results/autocomplete_suggestions' ) );
$facetField->setPrefix( $escapedQueryString );

$solariumResult = $this->_client->select( $query );

if ($solariumResult) {
return $solariumResult->getFacetSet()->getFacet( 'text' );
} else {
return null;
$result = array();
foreach ( $solariumResult->getFacetSet()->getFacet( 'auto_complete' ) as $term => $matches ) {
if ( $matches ) {
$result[ $term ] = $matches;
}
};
}

return $result;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,20 @@ function prepareResult(
$query
) {
if (JeroenVermeulen_Solarium_Model_Engine::isEnabled( $query->getStoreId() )) {
$helper = Mage::helper('jeroenvermeulen_solarium');
$adapter = $this->_getWriteAdapter();
$searchResultTable = $this->getTable( 'catalogsearch/result' );
$catSearchHelper = Mage::helper('catalogsearch');
/** @var JeroenVermeulen_Solarium_Model_Engine $engine */
$engine = Mage::getSingleton( 'jeroenvermeulen_solarium/engine' );
if ($engine->isWorking()) {
$searchResult = $engine->search( $query->getStoreId(), $queryText );
if (false !== $searchResult) {
if (0 == count( $searchResult )) {
Mage::register( 'solarium_search_result', $searchResult );
/** @deprecated The registry key 'solarium_suggest' is deprecated, it was used in 1.6.0 till 1.6.2 */
Mage::register( 'solarium_suggest', $searchResult->getSuggestions() );
$resultProducts = $searchResult->getResultProducts();
if ( is_array($resultProducts) ) {
if (0 == count( $resultProducts )) {
// No results, we need to check if the index is empty.
if ($engine->isEmpty( $query->getStoreId() )) {
Mage::Log( sprintf( '%s - Warning: index is empty', __CLASS__ ), Zend_Log::WARN );
Expand All @@ -59,7 +65,7 @@ function prepareResult(
$columns = array( 'query_id', 'product_id', 'relevance' );
$insertRows = array();
$queryId = $query->getId();
foreach ($searchResult as $data) {
foreach ($resultProducts as $data) {
$insertRows[ ] = array( $queryId, $data[ 'product_id' ], $data[ 'relevance' ] );
}
$adapter->beginTransaction();
Expand All @@ -69,6 +75,23 @@ function prepareResult(
$query->setIsProcessed( 1 );
}
}
// Autocorrect notification
if ( $searchResult->didAutoCorrect() ) {
$catSearchHelper->addNoteMessage(
$helper->__( "Showing results for '%s' instead.", $searchResult->getResultQuery() ) );
}
// "Did you mean" suggestions
$suggestions = $searchResult->getSuggestions();
if ( $suggestions ) {
$suggestHtml = '';
foreach ($suggestions as $suggestion => $result_count) {
$title = $helper->__('Results').':'.$result_count;
$href = Mage::getUrl('catalogsearch/result', array('q' => $suggestion));
$suggestHtml .= sprintf('&nbsp; <a title="%s" href="%s">', $title, $href);
$suggestHtml .= $suggestion . '</a>';
}
$catSearchHelper->addNoteMessage( $helper->__('Did you mean:') . $suggestHtml );
}
}
}
if (!$query->getIsProcessed()) {
Expand Down
49 changes: 49 additions & 0 deletions app/code/community/JeroenVermeulen/Solarium/Model/SearchResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* JeroenVermeulen_Solarium
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this Module to
* newer versions in the future.
*
* @category JeroenVermeulen
* @package JeroenVermeulen_Solarium
* @copyright Copyright (c) 2014 Jeroen Vermeulen (http://www.jeroenvermeulen.eu)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/

/**
* Class JeroenVermeulen_Solarium_Model_SearchResult
*
* Container for search result data from Solr.
* When a search has been executed, this object is available via:
* Mage::registry( 'solarium_search_result' );
*
* @method setStoreId( int $storeId )
* @method int getStoreId()
* @method setUserQuery( string $query )
* @method string getUserQuery()
* @method setResultQuery( string $query )
* @method string getResultQuery()
* @method JeroenVermeulen_Solarium_Model_SearchResult setResultProducts($data)
* @method array getResultProducts()
* @method JeroenVermeulen_Solarium_Model_SearchResult setSuggestions($data)
* @method array getSuggestions()
*/
class JeroenVermeulen_Solarium_Model_SearchResult extends Mage_Core_Model_Abstract
{
// Most of the work is done by Magento's Mage_Core_Model_Abstract.

/** @return bool - True if autocorrect changed the the string to search for. */
public function didAutoCorrect() {
return( $this->getUserQuery() && $this->getResultQuery() && $this->getUserQuery() != $this->getResultQuery() );
}
}
85 changes: 60 additions & 25 deletions app/code/community/JeroenVermeulen/Solarium/Model/SelfTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ function test( $param )
{
$this->message = '';
$ok = true;
$allOk = true;
$insertOk = true;
$helper = Mage::helper( 'jeroenvermeulen_solarium' );
try {
$testProductId = intval( time() . getmypid() );
$testProduct = 'SELF TEST ENTRY ' . $testProductId;
$defaultParam = array(
$testProductId = intval( time() . getmypid() );
$testProduct = 'SELF TEST ENTRY ' . $testProductId;
$testAutoComplete = substr( $testProductId, 0, -3 );
$testAutoCorrect = 'SELF T3ST ENTRY ' . $testProductId;
$defaultParam = array(
'host' => '',
'port' => '',
'path' => '',
Expand All @@ -52,29 +56,37 @@ function test( $param )
);
$param = array_merge( $defaultParam, $param );
$config = array(
'general/enabled' => true,
'server/host' => $param[ 'host' ],
'server/port' => $param[ 'port' ],
'server/path' => $param[ 'path' ],
'server/core' => $param[ 'core' ],
'server/requires_authentication' => $param[ 'auth' ],
'server/username' => $param[ 'username' ],
'server/search_timeout' => $param[ 'timeout' ],
'server/password' => $param[ 'password' ]
'general/enabled' => true,
'server/host' => $param[ 'host' ],
'server/port' => $param[ 'port' ],
'server/path' => $param[ 'path' ],
'server/core' => $param[ 'core' ],
'server/requires_authentication' => $param[ 'auth' ],
'server/username' => $param[ 'username' ],
'server/search_timeout' => $param[ 'timeout' ],
'server/password' => $param[ 'password' ],
'results/autocomplete_suggestions' => 25,
'results/autocorrect' => 1,
'results/did_you_mean' => 1,
'results/did_you_mean_suggestions' => 5,
'results/max' => 100
);

/** @var JeroenVermeulen_Solarium_Model_Engine $engine */
if ($ok) {
$engine = Mage::getModel( 'jeroenvermeulen_solarium/engine', $config );
$ok = $engine->isWorking();
$allOk = $allOk and $ok;
$this->addMessage( 'Connection to Solr', $ok, 'Please check the connection settings.' );
}
if ($ok) {
$ok = $engine->ping();
$ok = $engine->ping();
$allOk = $allOk and $ok;
$this->addMessage( 'Ping Solr', $ok, 'Please check the connection settings.' );
}
if ($ok) {
$ok = $engine->getClient()->checkMinimal( '3.0' );
$ok = $engine->getClient()->checkMinimal( '3.0' );
$allOk = $allOk and $ok;
$this->addMessage( 'Check Solr version', $ok, 'Solr server version must be 3.0 or greater.' );
}
if ($ok) {
Expand All @@ -90,36 +102,59 @@ function test( $param )
$buffer->createDocument( $data );
$solariumResult = $buffer->commit();
$engine->optimize(); // ignore result
$ok = $engine->processResult( $solariumResult, 'flushing buffered add' );
$insertOk = $engine->processResult( $solariumResult, 'flushing buffered add' );
$allOk = $insertOk and $ok;
$this->addMessage(
'Inserting test entry in Solr',
$ok,
$insertOk,
'Make sure you install the "schema.xml" and "solrconfig.xml"
provided by this extension, and restart Solr.'
provided by this extension, and restart Solr.'
);
}
if ($ok) {
$resultDocs = $engine->search( $this::TEST_STOREID, $testProduct );
$ok = false;
if ($insertOk) {
$searchResult = $engine->search( $this::TEST_STOREID, $testProduct );
$resultDocs = $searchResult->getResultProducts();
$ok = false;
$allOk = $allOk and $ok;
foreach ($resultDocs as $resultDoc) {
if ($testProductId == $resultDoc[ 'product_id' ]) {
$ok = true;
}
}
$this->addMessage( 'Search for test entry', $ok );
}
if ($ok) {
$ok = $engine->cleanIndex( $this::TEST_STOREID, array( $testProductId ) );
$autoSuggest = $engine->getAutoSuggestions( $this::TEST_STOREID, $testAutoComplete );
$ok = false;
$allOk = $allOk and $ok;
foreach ($autoSuggest as $term => $count) {
if ( $testProductId == $term && 0 < $count ) {
$ok = true;
}
}
$this->addMessage( 'Test Autocomplete', $ok );

$searchResult = $engine->search( $this::TEST_STOREID, $testAutoCorrect );
$resultDocs = $searchResult->getResultProducts();
$ok = false;
$allOk = $allOk and $ok;
foreach ($resultDocs as $resultDoc) {
if ($testProductId == $resultDoc[ 'product_id' ]) {
$ok = true;
}
}
$this->addMessage( 'Test Suggest + Correct Typos', $ok );

$ok = $engine->cleanIndex( $this::TEST_STOREID, array( $testProductId ) );
$allOk = $allOk and $ok;
$this->addMessage( 'Deleting test entry from Solr', $ok );
}
} catch ( Exception $e ) {
$ok = false;
$allOk = false;
$this->message .= '<tr>';
$this->message .= '<td class="label error">ERROR</td>';
$this->message .= '<td class="value error">' . $e->getMessage() . '</td>';
$this->message .= '</tr>';
}
if (!$ok) {
if (!$allOk) {
$this->message .= '<tr>';
$wikiText = $helper->__( 'You can find the Installation Instructions and FAQ in [our Wiki on GitHub].' );
$wikiText = str_replace( '[', '<a href="' . $this::WIKI_URL . '" target="_blank">', $wikiText );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,4 @@
</action>
</reference>
</default>
<catalogsearch_result_index>
<reference name="content">
<block type="core/template" template="jeroenvermeulen/solarium/suggest.phtml" before="-" />
</reference>
</catalogsearch_result_index>
</layout>

This file was deleted.

Loading

0 comments on commit b308b60

Please sign in to comment.