Skip to content

Commit

Permalink
[bug 1215110] Refactor simple and advanced search
Browse files Browse the repository at this point in the history
* centralize duplicate code to both get it out of the way and also make
  it easier to reason about
* remove intermediary variables that aren't needed
* clean up comments
* reduce complexity
* reorganize view into the same 5 steps the basic view is in
* nix ComposedList use in search views
  • Loading branch information
willkg committed Nov 3, 2015
1 parent 4859eb8 commit e0a2f79
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 414 deletions.
49 changes: 49 additions & 0 deletions kitsune/search/es_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
import logging
import pprint
import time
from functools import wraps

from django.conf import settings
from django.db import reset_queries
from django.http import HttpResponse
from django.shortcuts import render

import requests
from elasticutils import S as UntypedS
from elasticutils.contrib.django import S, F, get_es, ES_EXCEPTIONS # noqa
from statsd import statsd
from tower import ugettext as _

from kitsune.search import config
from kitsune.search.utils import chunked
Expand Down Expand Up @@ -886,3 +890,48 @@ def indexes_for_doctypes(doctype):
# Import locally to avoid circular import.
from kitsune.search.models import get_mapping_types
return set(d.get_index() for d in get_mapping_types(doctype))


def handle_es_errors(template, status_code=503):
"""Handles Elasticsearch exceptions for views
Wrap the entire view in this and don't worry about Elasticsearch exceptions
again!
:arg template: template path string or function to generate the template
path string for HTML requests
:arg status_code: status code to return
:returns: content-type-appropriate HttpResponse
"""
def handler(fun):
@wraps(fun)
def _handler(request, *args, **kwargs):
try:
return fun(request, *args, **kwargs)

except ES_EXCEPTIONS as exc:
is_json = (request.GET.get('format') == 'json')
callback = request.GET.get('callback', '').strip()
content_type = 'application/x-javascript' if callback else 'application/json'
if is_json:
return HttpResponse(
json.dumps({'error': _('Search Unavailable')}),
content_type=content_type,
status=status_code)

# If template is a function, call it with the request, args
# and kwargs to get the template.
if callable(template):
actual_template = template(request, *args, **kwargs)
else:
actual_template = template

# Log exceptions so this isn't failing silently
log.exception(exc)

return render(request, actual_template, status=503)

return _handler
return handler
6 changes: 6 additions & 0 deletions kitsune/search/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ def clean(self):
c['num_votes'] = c.get('num_votes') or 0
return c

def clean_category(self):
category = self.cleaned_data['category']
if not category:
category = settings.SEARCH_DEFAULT_CATEGORIES
return category

def set_allowed_forums(self, user):
"""Sets the 'forum' field choices to forums the user can see."""
forums = [(f.id, f.name)
Expand Down
37 changes: 20 additions & 17 deletions kitsune/search/simple_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,28 @@
from kitsune.wiki.models import DocumentMappingType


def apply_boosts(searcher):
"""Returns searcher with boosts applied"""
return searcher.boost(
question_title=4.0,
question_content=3.0,
question_answer_content=3.0,
post_title=2.0,
post_content=1.0,
document_title=6.0,
document_content=1.0,
document_keywords=8.0,
document_summary=2.0,

# Text phrases in document titles and content get an extra boost.
document_title__match_phrase=10.0,
document_content__match_phrase=8.0)


def generate_simple_search(search_form, language, with_highlights=False):
"""Generates an S given a form
:arg search_form: a SimpleSearch form that's already had ``.is_valid()``
called on it
:arg search_form: a validated SimpleSearch form
:arg language: the language code
:arg with_highlights: whether or not to ask for highlights
Expand Down Expand Up @@ -76,21 +93,7 @@ def generate_simple_search(search_form, language, with_highlights=False):
number_of_fragments=0
)

# Set up boosts
searcher = searcher.boost(
question_title=4.0,
question_content=3.0,
question_answer_content=3.0,
document_title=6.0,
document_content=1.0,
document_keywords=8.0,
document_summary=2.0,

# Text phrases in document titles and content get an extra
# boost.
document_title__match_phrase=10.0,
document_content__match_phrase=8.0
)
searcher = apply_boosts(searcher)

# Build the query
query_fields = chain(*[
Expand Down
3 changes: 2 additions & 1 deletion kitsune/search/tests/test_search_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ def test_sortby_documents_helpful(self):
# r2.document should come first with 1 vote.
response = self.client.get(reverse('search.advanced'), {
'w': '1', 'a': '1', 'sortby_documents': 'helpful',
'format': 'json'})
'format': 'json'
})
eq_(200, response.status_code)

content = json.loads(response.content)
Expand Down
Loading

0 comments on commit e0a2f79

Please sign in to comment.