Пример #1
0
    def test_sphinx_indexer(self):
        """
        This tests that sphinx will properly index an addon.
        """

        # we have to specify to sphinx to look at test_ dbs
        c = SearchClient()
        results = c.query('Delicious')
        assert results[0].id == 3615, results
Пример #2
0
    def test_sphinx_indexer(self):
        """
        This tests that sphinx will properly index an addon.
        """

        # we have to specify to sphinx to look at test_ dbs
        c = SearchClient()
        results = c.query('Delicious')
        assert results[0].id == 3615, results
Пример #3
0
    def process_request(self,
                        query,
                        addon_type='ALL',
                        limit=10,
                        platform='ALL',
                        version=None):
        """
        This queries sphinx with `query` and serves the results in xml.
        """
        if query.startswith('guid:'):
            return self.guid_search(query, limit)

        sc = SearchClient()
        limit = min(MAX_LIMIT, int(limit))

        opts = {'app': self.request.APP.id}

        if addon_type.upper() != 'ALL':
            try:
                opts['type'] = int(addon_type)
            except ValueError:
                # `addon_type` is ALL or a type id.  Otherwise we ignore it.
                pass

        if version:
            opts['version'] = version

        if platform.upper() != 'ALL':
            opts['platform'] = platform.lower()

        if self.version < 1.5:
            # By default we show public addons only for api_version < 1.5
            opts['status'] = [amo.STATUS_PUBLIC]

            # Fix doubly encoded query strings
            try:
                query = urllib.unquote(query.encode('ascii'))
            except UnicodeEncodeError:
                # This fails if the string is already UTF-8.
                pass
        try:
            results = sc.query(query, limit=limit, **opts)
        except SearchError:
            return self.render_msg('Could not connect to Sphinx search.',
                                   ERROR,
                                   status=503,
                                   mimetype=self.mimetype)

        return self.render('api/search.xml', {
            'results': results,
            'total': sc.total_found
        })
Пример #4
0
def search(request, tag_name=None, template=None):
    # If the form is invalid we still want to have a query.
    query = request.REQUEST.get('q', '')

    search_opts = {
            'meta': ('versions', 'categories', 'tags', 'platforms'),
            'version': None,
            }

    form = SearchForm(request)
    form.is_valid()  # Let the form try to clean data.

    category = form.cleaned_data.get('cat')

    if category == 'collections':
        return _collections(request)
    elif category == 'personas':
        return _personas(request)

    # TODO: Let's change the form values to something less gross when
    # Remora dies in a fire.
    query = form.cleaned_data['q']

    addon_type = form.cleaned_data.get('atype', 0)
    tag = tag_name if tag_name is not None else form.cleaned_data.get('tag')
    if tag_name:
        search_opts['show_personas'] = True
    page = form.cleaned_data['page']
    sort = form.cleaned_data.get('sort')

    search_opts['version'] = form.cleaned_data.get('lver')
    search_opts['limit'] = form.cleaned_data.get('pp', DEFAULT_NUM_RESULTS)
    search_opts['platform'] = form.cleaned_data.get('pid', amo.PLATFORM_ALL)
    search_opts['sort'] = sort
    search_opts['app'] = request.APP.id
    search_opts['offset'] = (page - 1) * search_opts['limit']

    if category:
        search_opts['category'] = category
    elif addon_type:
        search_opts['type'] = addon_type

    search_opts['tag'] = tag

    client = SearchClient()

    try:
        results = client.query(query, **search_opts)
    except SearchError, e:
        log.error('Sphinx Error: %s' % e)
        return jingo.render(request, 'search/down.html', locals(), status=503)
Пример #5
0
    def process_request(self, query, addon_type='ALL', limit=10,
                        platform='ALL', version=None):
        """
        This queries sphinx with `query` and serves the results in xml.
        """
        sc = SearchClient()
        limit = min(MAX_LIMIT, int(limit))

        opts = {'app': self.request.APP.id}

        if addon_type.upper() != 'ALL':
            try:
                opts['type'] = int(addon_type)
            except ValueError:
                # `addon_type` is ALL or a type id.  Otherwise we ignore it.
                pass

        if version:
            opts['version'] = version

        if platform.upper() != 'ALL':
            opts['platform'] = platform.lower()

        # By default we show public addons only for api_version < 1.5
        statuses = [amo.STATUS_PUBLIC]

        if (self.version >= 1.5
            and not self.request.REQUEST.get('hide_sandbox')):
            statuses.append(amo.STATUS_UNREVIEWED)

        opts['status'] = statuses

        # Fix doubly encoded query strings
        if self.version < 1.5:
            try:
                query = urllib.unquote(query.encode('ascii'))
            except UnicodeEncodeError:
                # This fails if the string is already UTF-8.
                pass
        try:
            results = sc.query(query, limit=limit, **opts)
        except SearchError:
            return self.render_msg('Could not connect to Sphinx search.',
                                   ERROR, status=503, mimetype=self.mimetype)

        return self.render('api/search.xml',
                           {'results': results, 'total': sc.total_found})
Пример #6
0
def ajax_search(request):
    """ Returns a json feed of ten results for auto-complete used in
    collections.
    [
        {"id": 123, "name": "best addon", "icon": "http://path/to/icon"},
        ...
    ]
    """

    q = request.GET.get('q', '')
    client = SearchClient()
    try:
        results = client.query(q, limit=10)
        items = [dict(id=result.id, label=unicode(result.name),
                      icon=result.icon_url, value=unicode(result.name).lower())
                 for result in results]
    except SearchError:
        items = []

    return HttpResponse(json.dumps(items), mimetype='application/json')
Пример #7
0
def ajax_search(request):
    """ Returns a json feed of ten results for auto-complete used in
    collections.
    [
        {"id": 123, "name": "best addon", "icon": "http://path/to/icon"},
        ...
    ]
    """

    q = request.GET.get('q', '')
    client = SearchClient()
    try:

        results = client.query('@name ' + q, limit=10,
                               match=sphinx.SPH_MATCH_EXTENDED2)
        return [dict(id=result.id, label=unicode(result.name),
                     icon=result.icon_url, value=unicode(result.name).lower())
                for result in results]
    except SearchError:
        return []
Пример #8
0
def ajax_search(request):
    """ Returns a json feed of ten results for auto-complete used in
    collections.
    [
        {"id": 123, "name": "best addon", "icon": "http://path/to/icon"},
        ...
    ]
    """

    q = request.GET.get('q', '')
    client = SearchClient()
    try:

        results = client.query('@name ' + q, limit=10,
                               match=sphinx.SPH_MATCH_EXTENDED2)
        return [dict(id=result.id, label=unicode(result.name),
                     icon=result.icon_url, value=unicode(result.name).lower())
                for result in results]
    except SearchError:
        return []
Пример #9
0
    def process_request(self, query, addon_type="ALL", limit=10, platform="ALL", version=None):
        """
        This queries sphinx with `query` and serves the results in xml.
        """
        sc = SearchClient()

        opts = {"app": self.request.APP.id}

        if addon_type.upper() != "ALL":
            try:
                opts["type"] = int(addon_type)
            except ValueError:
                # `addon_type` is ALL or a type id.  Otherwise we ignore it.
                pass

        if version:
            opts["version"] = version

        if platform.upper() != "ALL":
            opts["platform"] = platform.lower()

        # By default we show public addons only for api_version < 1.5
        statuses = [amo.STATUS_PUBLIC]

        if self.version >= 1.5 and not self.request.REQUEST.get("hide_sandbox"):
            statuses.append(amo.STATUS_SANDBOX)

        opts["status"] = statuses

        # Fix doubly encoded query strings
        if self.version < 1.5:
            query = urllib.unquote(query.encode("ascii"))

        try:
            results = sc.query(query, limit=int(limit), **opts)
        except SearchError:
            return self.render_msg("Could not connect to Sphinx search.", ERROR, status=503, mimetype=self.mimetype)

        if self.format == "xml":
            return self.render("api/search.xml", {"results": results, "total": sc.total_found})
Пример #10
0
    def _sphinx_api_search(self, query, addon_type="ALL", limit=10, platform="ALL", version=None, compat_mode="strict"):
        """
        This queries sphinx with `query` and serves the results in xml.
        """
        sc = SearchClient()
        limit = min(MAX_LIMIT, int(limit))

        opts = {"app": self.request.APP.id}

        if addon_type.upper() != "ALL":
            try:
                opts["type"] = int(addon_type)
            except ValueError:
                # `addon_type` is ALL or a type id. Otherwise we ignore it.
                pass

        if version:
            opts["version"] = version

        if platform.upper() != "ALL":
            opts["platform"] = platform.lower()

        if self.version < 1.5:
            # By default we show public addons only for api_version < 1.5
            opts["status"] = [amo.STATUS_PUBLIC]

            # Fix doubly encoded query strings
            try:
                query = urllib.unquote(query.encode("ascii"))
            except UnicodeEncodeError:
                # This fails if the string is already UTF-8.
                pass
        try:
            results = sc.query(query, limit=limit, **opts)
        except SearchError:
            return self.render_msg("Could not connect to Sphinx search.", ERROR, status=503, mimetype=self.mimetype)

        return self.render("api/search.xml", {"results": results, "total": sc.total_found})
Пример #11
0
def _get_results(request, meta=[], client=None):
    form = ReporterSearchForm(request.GET)
    if form.is_valid():
        data = form.cleaned_data
        query = data.get('q', '')
        product = data.get('product') or FIREFOX.short
        version = data.get('version')
        search_opts = _get_results_opts(request, data, product, meta)
        c = client or Client()
        opinions = c.query(query, **search_opts)
        metas = c.meta
    else:
        opinions = []
        product = request.default_prod
        query = ''
        version = Version(LATEST_BETAS[product]).simplified
        metas = {}

    product = PRODUCTS.get(product, FIREFOX)

    return (opinions, form, product, version, metas)
Пример #12
0
def _get_results(request, meta=[], client=None):
    form = ReporterSearchForm(request.GET)
    if form.is_valid():
        data = form.cleaned_data
        query = data.get('q', '')
        product = data.get('product') or request.default_prod.short
        version = data.get('version')
        search_opts = _get_results_opts(request, data, product, meta)
        type_filter = search_opts['type'] if 'type' in search_opts else None
        c = client or Client()
        opinions = c.query(query, **search_opts)
        metas = c.meta
    else:
        opinions = []
        type_filter = None
        product = request.default_prod
        query = ''
        version = (getattr(product, 'default_version', None)
                   or Version(LATEST_BETAS[product]).simplified)
        metas = {}

    product = PRODUCTS.get(product, FIREFOX)

    return (opinions, form, product, version, metas, type_filter)
Пример #13
0
def dashboard(request):
    """Front page view."""

    # Defaults
    app = request.default_app
    version = simplify_version(LATEST_BETAS[app])

    # Frequent terms
    term_params = {
        'product': app.id,
        'version': version,
    }

    frequent_terms = Term.objects.frequent(
        **term_params)[:settings.TRENDS_COUNT]

    # opinions queryset for demographics
    latest_opinions = Opinion.objects.browse(**term_params)
    latest_beta = Opinion.objects.filter(version=version, product=app.id)

    # Sites clusters
    sites = SiteSummary.objects.filter(version__exact=version).filter(
        positive__exact=None).filter(os__exact=None)[:settings.TRENDS_COUNT]

    # search form to generate various form elements.
    search_form = ReporterSearchForm()

    try:
        c = Client()
        search_opts = dict(product=app.short, version=version)
        c.query('', meta=('type', 'locale', 'os', 'day_sentiment'), **search_opts)
        metas = c.meta
        daily = c.meta.get('day_sentiment', {})
        chart_data = dict(series=[
            dict(name=_('Praise'), data=daily['praise']),
            dict(name=_('Issues'), data=daily['issue']),
            dict(name=_('Suggestion'), data=daily['suggestion']),
            ],
            )
        total = c.total_found
    except SearchError:
        metas = {}
        total = latest_beta.count()
        chart_data = None

    data = {'opinions': latest_opinions.all()[:settings.MESSAGES_COUNT],
            'opinion_count': total,
            'opinion_types': OPINION_TYPES,
            'OPINION_PRAISE': OPINION_PRAISE,
            'OPINION_ISSUE': OPINION_ISSUE,
            'OPINION_SUGGESTION': OPINION_SUGGESTION,
            'product': app.short,
            'products': PROD_CHOICES,
            'sentiments': get_sentiment(metas.get('type', [])),
            'terms': stats.frequent_terms(qs=frequent_terms),
            'demo': dict(locale=metas.get('locale'), os=metas.get('os')),
            'sites': sites,
            'version': version,
            'versions': VERSION_CHOICES[app],
            'search_form': search_form,
            'chart_data_json': json.dumps(chart_data),
           }

    if not request.mobile_site:
        template = 'dashboard/dashboard.html'
    else:
        template = 'dashboard/mobile/dashboard.html'
    return jingo.render(request, template, data)
Пример #14
0
def dashboard(request):
    prod = request.default_prod
    version = getattr(prod, "default_version", None) or Version(LATEST_BETAS[prod]).simplified

    search_form = ReporterSearchForm()
    # Frequent terms
    term_params = {"product": prod.id, "version": version}

    # # opinions queryset for demographics
    latest_opinions = Opinion.objects.browse(**term_params)

    # # Sites clusters
    # sites = SiteSummary.objects.filter(version__exact=version).filter(
    #     positive__exact=None).filter(
    #     platform__exact=None)[:settings.TRENDS_COUNT]
    # sites = SiteSummary.objects.all()

    # Get the desktop site's absolute URL for use in the settings tab
    desktop_site = Site.objects.get(id=settings.DESKTOP_SITE_ID)

    try:
        c = Client()
        search_opts = dict(product=prod.short, version=version)
        c.query("", meta=("type", "locale", "manufacturer", "device", "day_sentiment"), **search_opts)
        metas = c.meta
        daily = c.meta.get("day_sentiment", {})
        chart_data = dict(
            series=[
                dict(name=_("Praise"), data=daily["praise"]),
                dict(name=_("Issues"), data=daily["issue"]),
                dict(name=_("Ideas"), data=daily["idea"]),
            ]
        )
        total = c.total_found
    except SearchError:
        metas = {}
        total = latest_opinions.count()
        chart_data = None

    data = {
        "opinions": latest_opinions.all()[: settings.MESSAGES_COUNT],
        "opinion_count": total,
        "product": prod,
        "products": PROD_CHOICES,
        "sent": get_sentiment(metas.get("type", [])),
        "locales": metas.get("locale"),
        "platforms": metas.get("platform"),
        "devices": metas.get("device"),
        "manufacturers": metas.get("manufacturer"),
        # 'sites': sites,
        "version": version,
        "versions": VERSION_CHOICES[prod],
        "chart_data_json": json.dumps(chart_data),
        "defaults": get_defaults(search_form),
        "search_form": search_form,
        "desktop_url": "http://" + desktop_site.domain,
    }

    if not request.mobile_site:
        template = "dashboard/beta.html"
    else:
        template = "dashboard/mobile/beta.html"
    return jingo.render(request, template, data)
Пример #15
0
def dashboard(request):
    """Beta dashboard."""
    # Defaults
    prod = request.default_prod
    version = Version(LATEST_BETAS[prod]).simplified

    search_form = ReporterSearchForm()
    # Frequent terms
    term_params = {
        'product': prod.id,
        'version': version,
    }

    frequent_terms = Term.objects.frequent(
        **term_params)[:settings.TRENDS_COUNT]

    # opinions queryset for demographics
    latest_opinions = Opinion.objects.browse(**term_params)
    latest_beta = Opinion.objects.filter(version=version, product=prod.id)

    # Sites clusters
    sites = SiteSummary.objects.filter(version__exact=version).filter(
        positive__exact=None).filter(
        platform__exact=None)[:settings.TRENDS_COUNT]

    try:
        c = Client()
        search_opts = dict(product=prod.short, version=version)
        c.query('', meta=('type', 'locale', 'platform', 'day_sentiment'),
                **search_opts)
        metas = c.meta
        daily = c.meta.get('day_sentiment', {})
        chart_data = dict(series=[
            dict(name=_('Praise'), data=daily['praise']),
            dict(name=_('Issues'), data=daily['issue']),
            dict(name=_('Ideas'), data=daily['idea']),
            ])
        total = c.total_found
    except SearchError:
        metas = {}
        total = latest_beta.count()
        chart_data = None

    data = {'opinions': latest_opinions.all()[:settings.MESSAGES_COUNT],
            'opinion_count': total,
            'product': prod,
            'products': PROD_CHOICES,
            'sentiments': get_sentiment(metas.get('type', [])),
            'terms': stats.frequent_terms(qs=frequent_terms),
            'locales': metas.get('locale'),
            'platforms': metas.get('platform'),
            'sites': sites,
            'version': version,
            'versions': VERSION_CHOICES[prod],
            'chart_data_json': json.dumps(chart_data),
            'defaults': get_defaults(search_form),
            'search_form': search_form,
           }

    if not request.mobile_site:
        template = 'dashboard/beta.html'
    else:
        template = 'dashboard/mobile/beta.html'
    return jingo.render(request, template, data)
Пример #16
0
def search(request, tag_name=None):
    # If the form is invalid we still want to have a query.
    query = request.REQUEST.get('q', '')

    search_opts = {
            'meta': ('versions', 'categories', 'tags'),
            'version': None,
            }

    form = SearchForm(request)
    form.is_valid()  # Let the form try to clean data.

    # TODO(davedash): remove this feature when we remove Application for
    # the search advanced form
    # Redirect if appid != request.APP.id

    appid = form.cleaned_data['appid']

    if request.APP.id != appid:
        new_app = amo.APP_IDS.get(appid)
        return HttpResponseRedirect(
                urlresolvers.get_app_redirect(new_app))

    category = form.cleaned_data.get('cat')

    if category == 'collections':
        return _collections(request)
    elif category == 'personas':
        return _personas(request)

    # TODO: Let's change the form values to something less gross when
    # Remora dies in a fire.
    query = form.cleaned_data['q']

    addon_type = form.cleaned_data.get('atype', 0)
    tag = tag_name if tag_name is not None else form.cleaned_data.get('tag')
    page = form.cleaned_data['page']
    last_updated = form.cleaned_data.get('lup')
    sort = form.cleaned_data.get('sort')

    search_opts['version'] = form.cleaned_data.get('lver')
    search_opts['limit'] = form.cleaned_data.get('pp', DEFAULT_NUM_RESULTS)
    search_opts['platform'] = form.cleaned_data.get('pid', amo.PLATFORM_ALL)
    search_opts['sort'] = sort
    search_opts['app'] = request.APP.id
    search_opts['offset'] = (page - 1) * search_opts['limit']

    delta_dict = {
            '1 day ago': timedelta(days=1),
            '1 week ago': timedelta(days=7),
            '1 month ago': timedelta(days=30),
            '3 months ago': timedelta(days=90),
            '6 months ago': timedelta(days=180),
            '1 year ago': timedelta(days=365),
            }

    delta = delta_dict.get(last_updated)

    if delta:
        search_opts['before'] = int(
                time.mktime((datetime.now() - delta).timetuple()))

    if category:
        search_opts['category'] = category
    elif addon_type:
        search_opts['type'] = addon_type

    search_opts['tag'] = tag

    client = SearchClient()

    try:
        results = client.query(query, **search_opts)
    except SearchError:
        return jingo.render(request, 'search/down.html', locals(), status=503)

    version_filters = client.meta['versions']

    # If we are filtering by a version, make sure we explicitly list it.
    if search_opts['version']:
        try:
            version_filters += (version_int(search_opts['version']),)
        except UnicodeEncodeError:
            pass  # We didn't want to list you anyway.

    versions = _get_versions(request, client.meta['versions'],
                             search_opts['version'])
    categories = _get_categories(request, client.meta['categories'],
                                 addon_type, category)
    tags = _get_tags(request, client.meta['tags'], tag)
    sort_tabs = _get_sorts(request, sort)

    pager = amo.utils.paginate(request, results, search_opts['limit'])

    return jingo.render(request, 'search/results.html', {
                'pager': pager, 'query': query, 'tag': tag,
                'versions': versions, 'categories': categories, 'tags': tags,
                'sort_tabs': sort_tabs, 'sort': sort})
Пример #17
0
 def test_alpha_sort(self):
     "This verifies that alpha sort is case insensitive."
     c = SearchClient()
     results = c.query('', sort='name')
     ordering = [unicode(a.name).lower() for a in results]
     eq_(ordering, sorted(ordering))
Пример #18
0
import datetime
import socket

from mock import patch
from nose.tools import eq_

import input
from feedback.models import Opinion
from search.client import Client, SearchError, extract_filters
from search.tests import SphinxTestCase

query = lambda x='', **kwargs: Client().query(x, **kwargs)
num_results = lambda x='', **kwargs: len(query(x, **kwargs))


class SearchTest(SphinxTestCase):
    def test_default_ordering(self):
        """Any query should return results in rev-chron order."""
        r = query()
        dates = [o.created for o in r]
        eq_(dates, sorted(dates, reverse=True), "These aren't revchron.")

        r = query('Firefox')
        dates = [o.created for o in r]
        eq_(dates, sorted(dates, reverse=True), "These aren't revchron.")

    @patch('search.client.sphinx.SphinxClient.RunQueries')
    def test_errors(self, sphinx):
        for error in (socket.timeout(), Exception(),):
            sphinx.side_effect = error
            self.assertRaises(SearchError, query)
Пример #19
0
 def test_alpha_sort(self):
     "This verifies that alpha sort is case insensitive."
     c = SearchClient()
     results = c.query('', sort='name')
     ordering = [unicode(a.name).lower() for a in results]
     eq_(ordering, sorted(ordering))
Пример #20
0
def dashboard(request):
    prod = request.default_prod
    version = (getattr(prod, 'default_version', None)
               or Version(LATEST_BETAS[prod]).simplified)

    search_form = ReporterSearchForm()
    # Frequent terms
    term_params = {
        'product': prod.id,
        'version': version,
    }

    # # opinions queryset for demographics
    latest_opinions = Opinion.objects.browse(**term_params)

    # # Sites clusters
    # sites = SiteSummary.objects.filter(version__exact=version).filter(
    #     positive__exact=None).filter(
    #     platform__exact=None)[:settings.TRENDS_COUNT]
    # sites = SiteSummary.objects.all()

    # Get the desktop site's absolute URL for use in the settings tab
    desktop_site = Site.objects.get(id=settings.DESKTOP_SITE_ID)

    try:
        c = Client()
        search_opts = dict(product=prod.short, version=version)
        c.query('',
                meta=('type', 'locale', 'manufacturer', 'device',
                      'day_sentiment'),
                **search_opts)
        metas = c.meta
        daily = c.meta.get('day_sentiment', {})
        chart_data = dict(series=[
            dict(name=_('Praise'), data=daily['praise']),
            dict(name=_('Issues'), data=daily['issue']),
            dict(name=_('Ideas'), data=daily['idea']),
        ])
        total = c.total_found
    except SearchError:
        metas = {}
        total = latest_opinions.count()
        chart_data = None

    data = {
        'opinions': latest_opinions.all()[:settings.MESSAGES_COUNT],
        'opinion_count': total,
        'product': prod,
        'products': PROD_CHOICES,
        'sent': get_sentiment(metas.get('type', [])),
        'locales': metas.get('locale'),
        'platforms': metas.get('platform'),
        'devices': metas.get('device'),
        'manufacturers': metas.get('manufacturer'),
        # 'sites': sites,
        'version': version,
        'versions': VERSION_CHOICES[prod],
        'chart_data_json': json.dumps(chart_data),
        'defaults': get_defaults(search_form),
        'search_form': search_form,
        'desktop_url': 'http://' + desktop_site.domain,
    }

    if not request.mobile_site:
        template = 'dashboard/beta.html'
    else:
        template = 'dashboard/mobile/beta.html'
    return jingo.render(request, template, data)
Пример #21
0
def search(request, tag_name=None):
    # If the form is invalid we still want to have a query.
    query = request.REQUEST.get('q', '')

    search_opts = {
            'meta': ('versions', 'categories', 'tags'),
            'version': None,
            }

    form = SearchForm(request)
    form.is_valid()  # Let the form try to clean data.

    # TODO(davedash): remove this feature when we remove Application for
    # the search advanced form
    # Redirect if appid != request.APP.id

    appid = form.cleaned_data['appid']

    if request.APP.id != appid:
        new_app = amo.APP_IDS.get(appid)
        return HttpResponseRedirect(
                urlresolvers.get_app_redirect(new_app))

    category = form.cleaned_data.get('cat')

    if category == 'collections':
        return _collections(request)
    elif category == 'personas':
        return _personas(request)

    # TODO: Let's change the form values to something less gross when
    # Remora dies in a fire.
    query = form.cleaned_data['q']

    addon_type = form.cleaned_data.get('atype', 0)
    tag = tag_name if tag_name is not None else form.cleaned_data.get('tag')
    page = form.cleaned_data['page']
    last_updated = form.cleaned_data.get('lup')
    sort = form.cleaned_data.get('sort')

    search_opts['version'] = form.cleaned_data.get('lver')
    search_opts['limit'] = form.cleaned_data.get('pp', DEFAULT_NUM_RESULTS)
    search_opts['platform'] = form.cleaned_data.get('pid', amo.PLATFORM_ALL)
    search_opts['sort'] = sort
    search_opts['app'] = request.APP.id
    search_opts['offset'] = (page - 1) * search_opts['limit']

    delta_dict = {
            '1 day ago': timedelta(days=1),
            '1 week ago': timedelta(days=7),
            '1 month ago': timedelta(days=30),
            '3 months ago': timedelta(days=90),
            '6 months ago': timedelta(days=180),
            '1 year ago': timedelta(days=365),
            }

    delta = delta_dict.get(last_updated)

    if delta:
        search_opts['before'] = int(
                time.mktime((datetime.now() - delta).timetuple()))

    if category:
        search_opts['category'] = category
    elif addon_type:
        search_opts['type'] = addon_type

    search_opts['tag'] = tag

    client = SearchClient()

    try:
        results = client.query(query, **search_opts)
    except SearchError, e:
        log.error('Sphinx Error: %s' %e)
        return jingo.render(request, 'search/down.html', locals(), status=503)