def output_suggestions(self, os, max_suggestions_per_word=3): """ Make suggestions. """ # similarity == matching_trigrams / (len1 + len2 - matching_trigrams) sql_query = """ SELECT word, nentry, similarity (word, %(word)s) AS sml FROM terms WHERE word %% %(word)s ORDER BY sml DESC, nentry DESC LIMIT %(suggestions)s;""" q = os.query.lower() sugg = [] for word in q.split(): if len(word) > 3: try: rows = BaseSearcher.SQLSearcher().execute( sql_query, { 'word': word, 'suggestions': max_suggestions_per_word + 1 }) for i, row in enumerate(rows): if i >= max_suggestions_per_word: break corr = row.word if corr != word: sugg.append((word, corr)) except DatabaseError: pass for word, corr in reversed(sugg): os.entries.insert( 0, self.did_you_mean(os, corr, q.replace(word, corr)))
def index(self, **kwargs): """ Output a search result page. """ os = BaseSearcher.OpenSearch() os.log_request('search') if 'default_prefix' in kwargs: raise cherrypy.HTTPError( 400, 'Bad Request. Unknown parameter: default_prefix') if os.start_index > BaseSearcher.MAX_RESULTS: raise cherrypy.HTTPError( 400, 'Bad Request. Parameter start_index too high') sql = BaseSearcher.SQLStatement() sql.query = 'SELECT *' sql.from_ = ['v_appserver_books_4 as books'] # let derived classes prepare the query try: self.setup(os, sql) except ValueError as what: raise cherrypy.HTTPError(400, 'Bad Request. ' + str(what)) os.fix_sortorder() # execute the query try: BaseSearcher.SQLSearcher().search(os, sql) except DatabaseError as what: cherrypy.log("SQL Error: " + str(what), context='REQUEST', severity=logging.ERROR) raise cherrypy.HTTPError(400, 'Bad Request. Check your query.') # sync os.title and first entry header if os.entries: entry = os.entries[0] if os.title and not entry.header: entry.header = os.title elif entry.header and not os.title: os.title = entry.header os.template = os.page = 'results' # give derived class a chance to tweak result set self.fixup(os) # warn user about no records found if os.total_results == 0: self.nothing_found(os) # suggest alternate queries if os.total_results < 5: self.output_suggestions(os) # add sort by links if os.start_index == 1 and os.total_results > 1: if 'downloads' in os.alternate_sort_orders: self.sort_by_downloads(os) if 'release_date' in os.alternate_sort_orders: self.sort_by_release_date(os) if 'title' in os.alternate_sort_orders: self.sort_by_title(os) if 'alpha' in os.alternate_sort_orders: self.sort_alphabetically(os) if 'quantity' in os.alternate_sort_orders: self.sort_by_quantity(os) os.finalize() self.finalize(os) if os.total_results > 0: # call this after finalize () os.entries.insert(0, self.status_line(os)) return self.format(os)
class Suggestions(Page.Page): """ Output the search suggestions page. """ sql_searcher = BaseSearcher.SQLSearcher() def index(self, **dummy_kwargs): """ Output the suggestions page. """ cherrypy.request.params['format'] = 'json' # override user os = BaseSearcher.OpenSearch() os.sort_order = 'nentry' os.start_index = 1 os.items_per_page = 5 if os.format != 'json': raise cherrypy.HTTPError(400, 'Bad Request. Unknown format.') if len(os.query) == 0: raise cherrypy.HTTPError(400, 'Bad Request. No query.') last_word = os.query.split()[-1] if len(last_word) < 4: raise cherrypy.HTTPError(400, 'Bad Request. Query too short.') # ok. request looks sane. process it os.log_request('suggestions') os.f_format_title = os.format_suggestion os.f_format_subtitle = os.format_none os.f_format_extra = os.format_none os.f_format_url = os.format_none os.f_format_thumb_url = os.format_none os.f_format_icon = os.format_none sql = BaseSearcher.SQLStatement() # prepare inner query sql.query = 'SELECT tsvec' sql.from_ = ('books', ) sql.fulltext('books.tsvec', os.query) inner_sql_query = self.sql_searcher.mogrify(os, sql) sql.query = "SELECT substr (word, 2) AS title FROM ts_stat ( %(inner)s )" sql.from_ = () sql.params['inner'] = inner_sql_query sql.where = ["word ~* %(re_word)s"] sql.params['re_word'] = '^0' + last_word try: os = self.sql_searcher.search(os, sql) except DatabaseError as what: cherrypy.log("SQL Error: " + str(what), context='REQUEST', severity=logging.ERROR) raise cherrypy.HTTPError(500, 'Internal Server Error.') os.template = os.page = 'results' os.finalize() return self.format(os)