Ejemplo n.º 1
0
    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)))
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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)