Show reddit search "facets"

If search results contain hits from more than one subreddit,
the top 20 will be selectable to click through and narrow
results
This commit is contained in:
Keith Mitchell
2012-07-09 14:01:30 -07:00
parent 3c0c27fab3
commit fa629e92c9
7 changed files with 101 additions and 32 deletions

View File

@@ -672,8 +672,8 @@ class FrontController(RedditController):
query = "(and %s timestamp:%s..%s)" % (query, start, end)
q = SearchQuery(query, raw_sort="-text_relevance",
syntax="cloudsearch")
num, t, pane = self._search(q, num=num, after=after, reverse=reverse,
count=count)
pane = self._search(q, num=num, after=after, reverse=reverse,
count=count)[2]
return LinkInfoPage(link=article, content=pane,
subtitle=_('related')).render()
@@ -705,14 +705,14 @@ class FrontController(RedditController):
"""Search reddits by title and description."""
q = SubredditSearchQuery(query)
num, t, spane = self._search(q, num=num, reverse=reverse,
after=after, count=count,
skip_deleted_authors=False)
results, etime, spane = self._search(q, num=num, reverse=reverse,
after=after, count=count,
skip_deleted_authors=False)
res = SubredditsPage(content=spane,
prev_search=query,
elapsed_time=t,
num_results=num,
elapsed_time=etime,
num_results=results.hits,
# update if we ever add sorts
search_params={},
title=_("search results"),
@@ -747,8 +747,9 @@ class FrontController(RedditController):
cleanup_message = None
try:
q = SearchQuery(query, site, sort, syntax=syntax)
num, t, spane = self._search(q, num=num, after=after,
reverse = reverse, count = count)
results, etime, spane = self._search(q, num=num, after=after,
reverse=reverse,
count=count)
except InvalidQuery:
# strip the query down to a whitelist
cleaned = re.sub("[^\w\s]+", " ", query)
@@ -756,12 +757,14 @@ class FrontController(RedditController):
# if it was nothing but mess, we have to stop
if not cleaned.strip():
num, t, spane = 0, 0, []
results, etime, spane = 0, 0, []
cleanup_message = strings.completely_invalid_search_query
else:
q = SearchQuery(cleaned, site, sort)
num, t, spane = self._search(q, num=num, after=after,
reverse=reverse, count=count)
results, etime, spane = self._search(q, num=num,
after=after,
reverse=reverse,
count=count)
cleanup_message = strings.invalid_search_query % {
"clean_query": cleaned
}
@@ -770,14 +773,17 @@ class FrontController(RedditController):
self.search_help_page
}
res = SearchPage(_('search results'), query, t, num, content=spane,
res = SearchPage(_('search results'), query, etime, results.hits,
content=spane,
nav_menus=[SearchSortMenu(default=sort)],
search_params=dict(sort=sort),
infotext=cleanup_message,
simple=False, site=c.site,
restrict_sr=restrict_sr,
syntax=syntax,
converted_data=q.converted_data
converted_data=q.converted_data,
facets=results.subreddit_facets,
sort=sort,
).render()
return res
@@ -805,7 +811,7 @@ class FrontController(RedditController):
return self.search_fail(e)
timing = time_module.time() - builder.start_time
return builder.total_num, timing, res
return builder.results, timing, res
@validate(VAdmin(),
comment = VCommentByID('comment_id'))

View File

@@ -477,18 +477,29 @@ def test_run_srs(*sr_names):
### Query Code ###
class Results(object):
__slots__ = ["docs", "hits", "facets"]
def __init__(self, docs, hits, facets):
self.docs = docs
self.hits = hits
self.facets = facets
self._facets = facets
self._subreddits = []
def __repr__(self):
return '%s(%r, %r, %r)' % (self.__class__.__name__,
self.docs,
self.hits,
self.facets)
self._facets)
@property
def subreddit_facets(self):
'''Filter out subreddits that the user isn't allowed to see'''
if not self._subreddits and 'reddit' in self._facets:
sr_facets = [(sr['value'], sr['count']) for sr in
self._facets['reddit']]
srs_by_name = Subreddit._by_name([sr[0] for sr in sr_facets])
self._subreddits = [sr for sr in sr_facets
if srs_by_name[sr[0]].can_view(c.user)]
return self._subreddits
def _to_fn(cls, id_):
@@ -505,7 +516,7 @@ INVALID_QUERY_CODES = ('CS-UnknownFieldInMatchExpression',
'CS-InvalidMatchSetExpression',
'CS-IncorrectFieldTypeInMatchExpression',
'CS-InvalidMatchSetExpression',)
def basic_query(query=None, bq=None, facets=("reddit",), facet_count=10,
def basic_query(query=None, bq=None, facets=("reddit",), facet_count=20,
size=1000, start=0, rank="hot", return_fields=None,
record_stats=False, search_api=None):
if search_api is None:
@@ -619,7 +630,7 @@ class CloudSearchQuery(object):
results = self._run(_update=_update)
docs, hits, facets = results.docs, results.hits, results.facets
docs, hits, facets = results.docs, results.hits, results._facets
after_docs = r2utils.get_after(docs, after, num, reverse=reverse)

View File

@@ -822,9 +822,9 @@ class SearchPage(BoringPage):
extra_page_classes = ['search-page']
def __init__(self, pagename, prev_search, elapsed_time,
num_results, search_params = {},
simple=False, restrict_sr = False, site=None,
syntax=None, converted_data=None,
num_results, search_params={},
simple=False, restrict_sr=False, site=None,
syntax=None, converted_data=None, facets={}, sort=None,
*a, **kw):
self.searchbar = SearchBar(prev_search=prev_search,
elapsed_time=elapsed_time,
@@ -832,7 +832,8 @@ class SearchPage(BoringPage):
search_params=search_params,
show_feedback=True, site=site,
simple=simple, restrict_sr=restrict_sr,
syntax=syntax, converted_data=converted_data)
syntax=syntax, converted_data=converted_data,
facets=facets, sort=sort)
BoringPage.__init__(self, pagename, robots='noindex', *a, **kw)
def content(self):
@@ -1745,7 +1746,8 @@ class SearchBar(Templated):
def __init__(self, header=None, num_results=0, prev_search='',
elapsed_time=0, search_params={}, show_feedback=False,
simple=False, restrict_sr=False, site=None, syntax=None,
subreddit_search=False, converted_data=None, **kw):
subreddit_search=False, converted_data=None, facets={},
sort=None, **kw):
if header is None:
header = _("previous search")
self.header = header
@@ -1764,7 +1766,8 @@ class SearchBar(Templated):
simple=simple, restrict_sr=restrict_sr,
site=site, syntax=syntax,
converted_data=converted_data,
subreddit_search=subreddit_search)
subreddit_search=subreddit_search, facets=facets,
sort=sort)
class Frame(Wrapped):
"""Frameset for the FrameToolbar used when a user hits /tb/. The

View File

@@ -513,6 +513,18 @@ def add_attr(attrs, kind, label=None, link=None, cssclass=None, symbol=None):
attrs.append( (priority, symbol, cssclass, label, link, img) )
def search_url(query, subreddit, restrict_sr="off", sort=None):
import urllib
url_query = {"q": query}
if restrict_sr:
url_query["restrict_sr"] = restrict_sr
if sort:
url_query["sort"] = sort
path = "/r/%s/search?" % subreddit if subreddit else "/search?"
path += urllib.urlencode(url_query)
return path
def format_number(number, locale=None):
if not locale:
locale = c.locale

View File

@@ -474,9 +474,9 @@ class SearchBuilder(IDBuilder):
self.start_time = time.time()
search = self.query.run()
names = list(search.docs)
self.total_num = search.hits
self.results = self.query.run()
names = list(self.results.docs)
self.total_num = self.results.hits
after = self.after._fullname if self.after else None

View File

@@ -1813,6 +1813,29 @@ label + #moresearchinfo {
text-decoration: underline;
}
.searchfacets {
overflow: auto;
font-size: small;
}
.searchfacets.title {
margin: 5px;
}
.searchfacets.list {
margin: 0px 0px 0px 10px;
}
li.searchfacet {
display: inline-block;
width: 15em;
}
.facet.count {
font-weight: bold;
color: #888888;
}
/* login, register */

View File

@@ -25,7 +25,7 @@
<%!
from r2.lib.strings import strings
from r2.lib.pages import SearchForm
from r2.lib.template_helpers import static
from r2.lib.template_helpers import static, search_url
%>
<% isize = 60 %>
@@ -72,4 +72,18 @@
simple=thing.simple, restrict_sr=thing.restrict_sr,
syntax=thing.syntax)}
</div>
</div>
%if thing.facets and len(thing.facets) > 1:
<div class="searchfacets">
<h4 class="searchfacets title">${_("too many results? narrow it down to a subreddit!")}</h4>
<ol class="searchfacets list">
%for facet in thing.facets:
<% subreddit, count = facet %>
<li class="searchfacet reddit">
<a class="facet title word" href="${search_url(thing.prev_search, subreddit, restrict_sr='on', sort=thing.sort)}">/r/${subreddit}</a>&nbsp;
<span class="facet count number">(${count})</span>
</li>&nbsp;
%endfor
</ol>
</div>
%endif
</div>