diff --git a/config/vufind/Summon.ini b/config/vufind/Summon.ini
index 36434aaf9a6c6257b962eceb9810349283a5b487..22c12f627a24900c72994e39dea1a3a18654870f 100644
--- a/config/vufind/Summon.ini
+++ b/config/vufind/Summon.ini
@@ -23,6 +23,7 @@ default_top_recommend[] = SummonBestBets
 ;default_top_recommend[] = TopFacets:FacetsTop:Summon
 default_side_recommend[] = SideFacets:Facets:CheckboxFacets:Summon
 default_noresults_recommend[] = SwitchType
+default_noresults_recommend[] = SwitchQuery:Summon
 
 ; Set this to true in order to highlight keywords from the search query when they
 ; appear in fields displayed in search results (may not apply to all fields).
diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini
index 7f076760631ad843c300372d3be127eaae9a4f24..ceefb2dbb0b3532e0cdaef8fa26a60d69729115f 100644
--- a/config/vufind/searches.ini
+++ b/config/vufind/searches.ini
@@ -41,6 +41,7 @@ case_sensitive_ranges = true
 default_top_recommend[] = TopFacets:ResultsTop
 default_side_recommend[] = SideFacets:Results:CheckboxFacets
 default_noresults_recommend[] = SwitchType
+default_noresults_recommend[] = SwitchQuery
 
 ; Set this to true in order to highlight keywords from the search query when they
 ; appear in fields displayed in search results.
@@ -270,6 +271,12 @@ CallNumber = callnumber
 ;
 ; Available modules recommended for use in the "no results" area:
 ;
+; SwitchQuery:[backend]:[checks to skip]
+;       This module analyzes the user's query and offers suggestions for ways to
+;       improve it. [backend] is the name of the search backend currently in use,
+;       which will help with accurate analysis (default = Solr). [checks to skip]
+;       is a comma-separated list of checks to disable; see the check*() methods
+;       in the module's code for a complete list of available checks.
 ; SwitchType:[field]:[field description]
 ;       If the current search type is not the same as [field], display a link
 ;       suggesting that the user try switching to [field].  [field description]
diff --git a/languages/en-gb.ini b/languages/en-gb.ini
index 882696344bb3a1b8f0074ca227192399ae2fdba0..66f061b9f226e3bbcda99b5644c8c87a81c883b8 100644
--- a/languages/en-gb.ini
+++ b/languages/en-gb.ini
@@ -562,8 +562,8 @@ Publication Frequency = "Publication Frequency"
 Published = Published
 Published in = "Published in"
 QR Code = "QR Code"
-qrcode_show = "Show QR Code"
 qrcode_hide = "Hide QR Code"
+qrcode_show = "Show QR Code"
 query time = "query time"
 Range = Range
 Range slider = "Range slider"
@@ -681,6 +681,10 @@ Summon Results = "Summon Results"
 summon_database_recommendations = "You may find additional resources here:"
 Supplied by Amazon = "Supplied by Amazon"
 Switch view to = "Switch view to"
+switchquery_intro = "You may be able to get more results by adjusting your search query."
+switchquery_unwantedbools = "The words AND, OR and NOT may confuse the search; try adding quotes"
+switchquery_unwantedquotes = "Removing quotes may allow a broader search"
+switchquery_wildcard = "Adding a wildcard symbol may retrieve word variants"
 System Unavailable = "System Unavailable"
 Table of Contents = "Table of Contents"
 Table of Contents unavailable = "Table of Contents unavailable"
diff --git a/languages/en.ini b/languages/en.ini
index 3831e015a93a08ad46cd0de2004bfe33cdd3e790..f8c6368e2d8c2c06f8ff85e332665115dfa26859 100644
--- a/languages/en.ini
+++ b/languages/en.ini
@@ -562,8 +562,8 @@ Publication Frequency = "Publication Frequency"
 Published = Published
 Published in = "Published in"
 QR Code = "QR Code"
-qrcode_show = "Show QR Code"
 qrcode_hide = "Hide QR Code"
+qrcode_show = "Show QR Code"
 query time = "query time"
 Range = Range
 Range slider = "Range slider"
@@ -681,6 +681,10 @@ Summon Results = "Summon Results"
 summon_database_recommendations = "You may find additional resources here:"
 Supplied by Amazon = "Supplied by Amazon"
 Switch view to = "Switch view to"
+switchquery_intro = "You may be able to get more results by adjusting your search query."
+switchquery_unwantedbools = "The words AND, OR and NOT may confuse the search; try adding quotes"
+switchquery_unwantedquotes = "Removing quotes may allow a broader search"
+switchquery_wildcard = "Adding a wildcard symbol may retrieve word variants"
 System Unavailable = "System Unavailable"
 Table of Contents = "Table of Contents"
 Table of Contents unavailable = "Table of Contents unavailable"
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index e4a6f0da1443aa19c399e6443fcef516504bba14..c199341bccc69f3235865b9a49d17c91bddd50e7 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -618,6 +618,11 @@ $config = array(
                             $sm->getServiceLocator()->get('VuFind\SearchResultsPluginManager')
                         );
                     },
+                    'switchquery' => function ($sm) {
+                        return new \VuFind\Recommend\SwitchQuery(
+                            $sm->getServiceLocator()->get('VuFind\Search\BackendManager')
+                        );
+                    },
                     'topfacets' => function ($sm) {
                         return new \VuFind\Recommend\TopFacets(
                             $sm->getServiceLocator()->get('VuFind\Config')
diff --git a/module/VuFind/src/VuFind/Recommend/SwitchQuery.php b/module/VuFind/src/VuFind/Recommend/SwitchQuery.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdf882a0a52af458cd5bda20d0c7e07bf4879e8c
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/SwitchQuery.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * SwitchQuery Recommendations Module
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:recommendation_modules Wiki
+ */
+namespace VuFind\Recommend;
+use VuFind\Search\BackendManager;
+
+/**
+ * SwitchQuery Recommendations Module
+ *
+ * This class recommends adjusting your search query to yield better results.
+ *
+ * @category VuFind2
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:recommendation_modules Wiki
+ */
+class SwitchQuery implements RecommendInterface
+{
+    /**
+     * Search backend identifier that we are working with.
+     *
+     * @var string
+     */
+    protected $backend;
+
+    /**
+     * Search backend plugin manager.
+     *
+     * @var BackendManager
+     */
+    protected $backendManager;
+
+    /**
+     * Improved query suggestions.
+     *
+     * @var array
+     */
+    protected $suggestions = array();
+
+    /**
+     * Names of checks that should be skipped. These should correspond
+     * with check method names -- e.g. to skip the check found in the
+     * checkWildcard() method, you would put 'wildcard' into this array.
+     *
+     * @var array
+     */
+    protected $skipChecks = array();
+
+    /**
+     * Constructor
+     *
+     * @param BackendManager $backendManager Search backend plugin manager
+     */
+    public function __construct(BackendManager $backendManager)
+    {
+        $this->backendManager = $backendManager;
+    }
+
+    /**
+     * setConfig
+     *
+     * Store the configuration of the recommendation module.
+     *
+     * @param string $settings Settings from searches.ini.
+     *
+     * @return void
+     */
+    public function setConfig($settings)
+    {
+        $params = explode(':', $settings);
+        $this->backend = !empty($params[0]) ? $params[0] : 'Solr';
+        $callback = function ($i) {
+            return trim(strtolower($i));
+        };
+        $this->skipChecks = !empty($params[1])
+            ? array_map($callback, explode(',', $params[1])) : array();
+    }
+
+    /**
+     * init
+     *
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\StdLib\Parameters    $request Parameter object representing user
+     * request.
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+    }
+
+    /**
+     * process
+     *
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $this->results = $results;
+
+        // We can't currently deal with advanced searches:
+        if ($this->results->getParams()->getSearchType() == 'advanced') {
+            return;
+        }
+
+        // Get the query to manipulate:
+        $query = $this->results->getParams()->getDisplayQuery();
+
+        // Perform all checks (based on naming convention):
+        $methods = get_class_methods($this);
+        $checks = array();
+        foreach ($methods as $method) {
+            if (substr($method, 0, 5) == 'check') {
+                $currentCheck = strtolower(substr($method, 5));
+                if (!in_array($currentCheck, $this->skipChecks)) {
+                    $result = $this->$method($query);
+                    if ($result) {
+                        $this->suggestions['switchquery_' . $currentCheck] = $result;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Does the query contain terms that are being treated as boolean operators,
+     * perhaps unintentionally?
+     *
+     * @param string $query Query to check
+     *
+     * @return string|bool
+     */
+    protected function checkUnwantedBools($query)
+    {
+        $query = trim($query);
+        $qb = $this->getQueryBuilder();
+        if (!$qb || !is_callable(array($qb, 'containsBooleans'))
+            || !$qb->containsBooleans($query)
+            || (substr($query, 0, 1) == '"' && substr($query, -1) == '"')
+        ) {
+            return false;
+        }
+        return '"' . addcslashes($query, '"') . '"';
+    }
+
+    /**
+     * Would removing quotes help?
+     *
+     * @param string $query Query to check
+     *
+     * @return string|bool
+     */
+    protected function checkUnwantedQuotes($query)
+    {
+        // Remove escaped quotes as they are of no consequence:
+        $query = str_replace('\"', ' ', $query);
+        return (strpos($query, '"') === false)
+            ? false : str_replace('"', ' ', $query);
+    }
+
+    /**
+     * Will adding a wildcard help?
+     *
+     * @param string $query Query to check
+     *
+     * @return string|bool
+     */
+    protected function checkWildcard($query)
+    {
+        // Don't pile wildcards on phrases:
+        if (substr($query, -1) == '"') {
+            return false;
+        }
+        $query = trim($query, ' ?');
+        return (substr($query, -1) != '*') ? $query . '*' : false;
+    }
+
+    /**
+     * Extract a query builder from the search backend.
+     *
+     * @return object
+     */
+    protected function getQueryBuilder()
+    {
+        $backend = $this->backendManager->get($this->backend);
+        return is_callable(array($backend, 'getQueryBuilder'))
+            ? $backend->getQueryBuilder() : false;
+    }
+
+    /**
+     * Get results stored in the object.
+     *
+     * @return \VuFind\Search\Base\Results
+     */
+    public function getResults()
+    {
+        return $this->results;
+    }
+
+    /**
+     * Get the new search handler, or false if it does not apply.
+     *
+     * @return array
+     */
+    public function getSuggestions()
+    {
+        return $this->suggestions;
+    }
+}
\ No newline at end of file
diff --git a/themes/blueprint/templates/Recommend/SwitchQuery.phtml b/themes/blueprint/templates/Recommend/SwitchQuery.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..bf0db3cc02e6a14c61a2b2d8af3a5d68d7006fa5
--- /dev/null
+++ b/themes/blueprint/templates/Recommend/SwitchQuery.phtml
@@ -0,0 +1,10 @@
+<? $suggestions = $this->recommend->getSuggestions(); if (!empty($suggestions)): ?>
+  <div class="info">
+    <p><?=$this->transEsc('switchquery_intro')?></p>
+    <ul>
+      <? foreach ($suggestions as $desc => $query): ?>
+        <li><?=$this->transEsc($desc)?>: <a href="<?=$this->recommend->getResults()->getUrlQuery()->setSearchTerms($query)?>"><?=$this->escapeHtml($query)?></a>.</li>
+      <? endforeach; ?>
+    </ul>
+  </div>
+<? endif; ?>
\ No newline at end of file
diff --git a/themes/bootstrap/templates/Recommend/SwitchQuery.phtml b/themes/bootstrap/templates/Recommend/SwitchQuery.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c4b98e50976ddd55d7d218aa1c025f1156ccbabd
--- /dev/null
+++ b/themes/bootstrap/templates/Recommend/SwitchQuery.phtml
@@ -0,0 +1,10 @@
+<? $suggestions = $this->recommend->getSuggestions(); if (!empty($suggestions)): ?>
+  <div class="alert alert-info">
+    <p><?=$this->transEsc('switchquery_intro')?></p>
+    <ul>
+      <? foreach ($suggestions as $desc => $query): ?>
+        <li><?=$this->transEsc($desc)?>: <a href="<?=$this->recommend->getResults()->getUrlQuery()->setSearchTerms($query)?>"><?=$this->escapeHtml($query)?></a>.</li>
+      <? endforeach; ?>
+    </ul>
+  </div>
+<? endif; ?>
\ No newline at end of file