From 590eb25c0cb398bfcfafe7511e93994ea4e8c731 Mon Sep 17 00:00:00 2001 From: Keith Mitchell Date: Tue, 11 Dec 2012 11:31:53 -0800 Subject: [PATCH] Add simple date drop down to search --- r2/r2/controllers/front.py | 16 +++++++---- r2/r2/lib/cloudsearch.py | 52 +++++++++++++++++++++------------- r2/r2/lib/pages/pages.py | 7 +++-- r2/r2/lib/template_helpers.py | 4 ++- r2/r2/templates/searchbar.html | 2 +- 5 files changed, 50 insertions(+), 31 deletions(-) diff --git a/r2/r2/controllers/front.py b/r2/r2/controllers/front.py index bd7c4c17e..bd1867ac8 100755 --- a/r2/r2/controllers/front.py +++ b/r2/r2/controllers/front.py @@ -776,11 +776,12 @@ class FrontController(RedditController, OAuth2ResourceController): @base_listing @validate(query=VLength('q', max_length=512), sort=VMenu('sort', SearchSortMenu, remember=False), + recent=VMenu('t', TimeMenu, remember=False), restrict_sr=VBoolean('restrict_sr', default=False), syntax=VOneOf('syntax', options=SearchQuery.known_syntaxes)) @api_doc(api_section.search, extensions=['json', 'xml']) - def GET_search(self, query, num, reverse, after, count, sort, restrict_sr, - syntax): + def GET_search(self, query, num, reverse, after, count, sort, recent, + restrict_sr, syntax): """Search links page.""" if query and '.' in query: url = sanitize_url(query, require_scheme = True) @@ -798,7 +799,8 @@ class FrontController(RedditController, OAuth2ResourceController): try: cleanup_message = None try: - q = SearchQuery(query, site, sort, syntax=syntax) + q = SearchQuery(query, site, sort, + recent=recent, syntax=syntax) results, etime, spane = self._search(q, num=num, after=after, reverse=reverse, count=count) @@ -810,7 +812,7 @@ class FrontController(RedditController, OAuth2ResourceController): cleaned = re.sub("[^\w\s]+", " ", query) cleaned = cleaned.lower().strip() - q = SearchQuery(cleaned, site, sort) + q = SearchQuery(cleaned, site, sort, recent=recent) results, etime, spane = self._search(q, num=num, after=after, reverse=reverse, @@ -828,8 +830,9 @@ class FrontController(RedditController, OAuth2ResourceController): res = SearchPage(_('search results'), query, etime, results.hits, content=spane, - nav_menus=[SearchSortMenu(default=sort)], - search_params=dict(sort=sort), + nav_menus=[SearchSortMenu(default=sort), + TimeMenu(default=recent)], + search_params=dict(sort=sort, t=recent), infotext=cleanup_message, simple=False, site=c.site, restrict_sr=restrict_sr, @@ -837,6 +840,7 @@ class FrontController(RedditController, OAuth2ResourceController): converted_data=q.converted_data, facets=results.subreddit_facets, sort=sort, + recent=recent, ).render() return res diff --git a/r2/r2/lib/cloudsearch.py b/r2/r2/lib/cloudsearch.py index 9c6d082ff..523fe5c0b 100644 --- a/r2/r2/lib/cloudsearch.py +++ b/r2/r2/lib/cloudsearch.py @@ -22,7 +22,7 @@ import collections import cPickle as pickle -from datetime import datetime +from datetime import datetime, timedelta import functools import httplib import json @@ -36,6 +36,7 @@ import l2cs from r2.lib import amqp, filters from r2.lib.db.operators import desc +from r2.lib.db.sorts import epoch_seconds import r2.lib.utils as r2utils from r2.models import (Account, Link, Subreddit, Thing, All, DefaultSR, MultiReddit, DomainSR, Friends, ModContribSR, @@ -797,12 +798,13 @@ class CloudSearchQuery(object): search_api = None sorts = {} sorts_menu_mapping = {} + recents = {None: None} known_syntaxes = ("cloudsearch", "lucene", "plain") default_syntax = "plain" lucene_parser = None def __init__(self, query, sr=None, sort=None, syntax=None, raw_sort=None, - faceting=None): + faceting=None, recent=None): if syntax is None: syntax = self.default_syntax elif syntax not in self.known_syntaxes: @@ -816,6 +818,8 @@ class CloudSearchQuery(object): self.sort = raw_sort else: self.sort = self.sorts[sort] + self._recent = recent + self.recent = self.recents[recent] self.faceting = faceting self.bq = u'' self.results = None @@ -936,7 +940,14 @@ class LinkSearchQuery(CloudSearchQuery): 'top': 4, 'comments': 5, } - + recents = { + 'hour': timedelta(hours=1), + 'day': timedelta(days=1), + 'week': timedelta(days=7), + 'month': timedelta(days=31), + 'year': timedelta(days=366), + 'all': None, + } schema = l2cs.make_schema(LinkFields.lucene_fieldnames()) lucene_parser = l2cs.make_parser( int_fields=LinkFields.lucene_fieldnames(type_=int), @@ -946,29 +957,30 @@ class LinkSearchQuery(CloudSearchQuery): default_syntax = "lucene" def customize_query(self, bq): + queries = [bq] subreddit_query = self._get_sr_restriction(self.sr) - return self.create_boolean_query(bq, subreddit_query) + if subreddit_query: + queries.append(subreddit_query) + if self.recent: + recent_query = self._restrict_recent(self.recent) + queries.append(recent_query) + return self.create_boolean_query(queries) @classmethod - def create_boolean_query(cls, query, subreddit_query): - '''Join a (user-entered) text query with the generated subreddit query - - Input: - base_query: user input from the search textbox - subreddit_query: output from _get_sr_restriction(sr) - - Test cases: - base_query: simple, simple with quotes, boolean, boolean w/ parens - subreddit_query: None, in parens '(or sr_id:1 sr_id:2 ...)', - without parens "author:'foo'" - - ''' - if subreddit_query: - bq = "(and %s %s)" % (query, subreddit_query) + def create_boolean_query(cls, queries): + '''Return an AND clause combining all queries''' + if len(queries) > 1: + bq = '(and ' + ' '.join(queries) + ')' else: - bq = query + bq = queries[0] return bq + @staticmethod + def _restrict_recent(recent): + now = datetime.now(g.tz) + since = epoch_seconds(now - recent) + return 'timestamp:%i..' % since + @staticmethod def _get_sr_restriction(sr): '''Return a cloudsearch appropriate query string that restricts diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index 5d6feadf8..ddc20a504 100755 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -922,6 +922,7 @@ class SearchPage(BoringPage): num_results, search_params={}, simple=False, restrict_sr=False, site=None, syntax=None, converted_data=None, facets={}, sort=None, + recent=None, *a, **kw): self.searchbar = SearchBar(prev_search=prev_search, elapsed_time=elapsed_time, @@ -930,7 +931,7 @@ class SearchPage(BoringPage): show_feedback=True, site=site, simple=simple, restrict_sr=restrict_sr, syntax=syntax, converted_data=converted_data, - facets=facets, sort=sort) + facets=facets, sort=sort, recent=recent) BoringPage.__init__(self, pagename, robots='noindex', *a, **kw) def content(self): @@ -1939,7 +1940,7 @@ class SearchBar(Templated): elapsed_time=0, search_params={}, show_feedback=False, simple=False, restrict_sr=False, site=None, syntax=None, subreddit_search=False, converted_data=None, facets={}, - sort=None, **kw): + sort=None, recent=None, **kw): if header is None: header = _("previous search") self.header = header @@ -1959,7 +1960,7 @@ class SearchBar(Templated): site=site, syntax=syntax, converted_data=converted_data, subreddit_search=subreddit_search, facets=facets, - sort=sort) + sort=sort, recent=recent) class Frame(Wrapped): """Frameset for the FrameToolbar used when a user hits /tb/. The diff --git a/r2/r2/lib/template_helpers.py b/r2/r2/lib/template_helpers.py index eaa2ca7ee..903725f86 100755 --- a/r2/r2/lib/template_helpers.py +++ b/r2/r2/lib/template_helpers.py @@ -516,7 +516,7 @@ 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): +def search_url(query, subreddit, restrict_sr="off", sort=None, recent=None): import urllib query = _force_utf8(query) url_query = {"q": query} @@ -524,6 +524,8 @@ def search_url(query, subreddit, restrict_sr="off", sort=None): url_query["restrict_sr"] = restrict_sr if sort: url_query["sort"] = sort + if recent: + url_query["t"] = recent path = "/r/%s/search?" % subreddit if subreddit else "/search?" path += urllib.urlencode(url_query) return path diff --git a/r2/r2/templates/searchbar.html b/r2/r2/templates/searchbar.html index 66df13bcc..ff2342755 100644 --- a/r2/r2/templates/searchbar.html +++ b/r2/r2/templates/searchbar.html @@ -80,7 +80,7 @@
    %for subreddit, count in thing.facets:
  1. - /r/${subreddit.name}  + /r/${subreddit.name}  (${count})
  2.   %endfor