##// END OF EJS Templates
search: added per-backend sorting fields....
dan -
r3968:2ec277c2 default
parent child Browse files
Show More
@@ -27,6 +27,16 b' from rhodecode.api.tests.utils import ('
27 27 @pytest.mark.usefixtures("testuser_api", "app")
28 28 class TestApiSearch(object):
29 29
30 @pytest.mark.parametrize("sort_dir", [
31 "asc",
32 "desc",
33 ])
34 @pytest.mark.parametrize("sort", [
35 "xxx",
36 "author_email",
37 "date",
38 "message",
39 ])
30 40 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
31 41 ('todo', 23, [
32 42 'vcs/backends/hg/inmemory.py',
@@ -55,10 +65,11 b' class TestApiSearch(object):'
55 65 'vcs/tests/test_cli.py']),
56 66 ('owner:michał test', 0, []),
57 67 ])
58 def test_search_content_results(self, query, expected_hits, expected_paths):
68 def test_search_content_results(self, sort_dir, sort, query, expected_hits, expected_paths):
59 69 id_, params = build_data(
60 70 self.apikey_regular, 'search',
61 71 search_query=query,
72 search_sort='{}:{}'.format(sort_dir, sort),
62 73 search_type='content')
63 74
64 75 response = api_call(self.app, params)
@@ -70,6 +81,16 b' class TestApiSearch(object):'
70 81 for expected_path in expected_paths:
71 82 assert expected_path in paths
72 83
84 @pytest.mark.parametrize("sort_dir", [
85 "asc",
86 "desc",
87 ])
88 @pytest.mark.parametrize("sort", [
89 "xxx",
90 "date",
91 "file",
92 "size",
93 ])
73 94 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
74 95 ('readme.rst', 3, []),
75 96 ('test*', 75, []),
@@ -77,10 +98,11 b' class TestApiSearch(object):'
77 98 ('extension:rst', 48, []),
78 99 ('extension:rst api', 24, []),
79 100 ])
80 def test_search_file_paths(self, query, expected_hits, expected_paths):
101 def test_search_file_paths(self, sort_dir, sort, query, expected_hits, expected_paths):
81 102 id_, params = build_data(
82 103 self.apikey_regular, 'search',
83 104 search_query=query,
105 search_sort='{}:{}'.format(sort_dir, sort),
84 106 search_type='path')
85 107
86 108 response = api_call(self.app, params)
@@ -110,9 +110,13 b' def perform_search(request, tmpl_context'
110 110 c.search_tags = search_tags
111 111
112 112 direction, sort_field = searcher.get_sort(search_type, search_sort)
113 c.sort = '{}:{}'.format(direction, sort_field)
114 c.sort_tag = sort_field
113 sort_definition = searcher.sort_def(search_type, direction, sort_field)
114 c.sort = ''
115 c.sort_tag = None
115 116 c.sort_tag_dir = direction
117 if sort_definition:
118 c.sort = '{}:{}'.format(direction, sort_field)
119 c.sort_tag = sort_field
116 120
117 121
118 122 class SearchView(BaseAppView):
@@ -89,6 +89,15 b' class BaseSearcher(object):'
89 89 """
90 90 return val
91 91
92 def sort_def(self, search_type, direction, sort_field):
93 """
94 Defines sorting for search. This function should decide if for given
95 search_type, sorting can be done with sort_field.
96
97 It also should translate common sort fields into backend specific. e.g elasticsearch
98 """
99 raise NotImplementedError()
100
92 101 @staticmethod
93 102 def get_sort(search_type, search_val):
94 103 """
@@ -99,6 +99,29 b' class WhooshSearcher(BaseSearcher):'
99 99 query = u'(%s) OR %s' % (query, hashes_or_query)
100 100 return query
101 101
102 def sort_def(self, search_type, direction, sort_field):
103
104 if search_type == 'commit':
105 field_defs = {
106 'message': 'message',
107 'date': 'date',
108 'author_email': 'author',
109 }
110 elif search_type == 'path':
111 field_defs = {
112 'file': 'path',
113 'size': 'size',
114 'lines': 'lines',
115 }
116 elif search_type == 'content':
117 # NOTE(dan): content doesn't support any sorting
118 field_defs = {}
119 else:
120 return ''
121
122 if sort_field in field_defs:
123 return field_defs[sort_field]
124
102 125 def search(self, query, document_type, search_user,
103 126 repo_name=None, repo_group_name=None,
104 127 requested_page=1, page_limit=10, sort=None, raise_on_exc=True):
@@ -124,21 +147,16 b' class WhooshSearcher(BaseSearcher):'
124 147 query = qp.parse(safe_unicode(query))
125 148 log.debug('query: %s (%s)', query, repr(query))
126 149
127 def sort_def(_direction, _sort_field):
128 field2whoosh = {
129 'message.raw': 'message',
130 'author.email.raw': 'author',
131 }
132 return field2whoosh.get(_sort_field) or _sort_field
133
134 150 reverse, sorted_by = False, None
135 151 direction, sort_field = self.get_sort(search_type, sort)
136 152 if sort_field:
137 if direction == Searcher.DIRECTION_DESC:
138 reverse = True
139 if direction == Searcher.DIRECTION_ASC:
140 reverse = False
141 sorted_by = sort_def(direction, sort_field)
153 sort_definition = self.sort_def(search_type, direction, sort_field)
154 if sort_definition:
155 sorted_by = sort_definition
156 if direction == Searcher.DIRECTION_DESC:
157 reverse = True
158 if direction == Searcher.DIRECTION_ASC:
159 reverse = False
142 160
143 161 whoosh_results = self.searcher.search(
144 162 query, filter=allowed_repos_filter, limit=None,
@@ -69,7 +69,7 b''
69 69 elif c.sort.startswith('desc:'):
70 70 return c.url_generator(sort='asc:{}'.format(field_name))
71 71
72 return 'asc:{}'.format(field_name)
72 return c.url_generator(sort='asc:{}'.format(field_name))
73 73 %>
74 74 </%def>
75 75
@@ -9,13 +9,13 b''
9 9 <th>${_('Commit')}</th>
10 10 <th></th>
11 11 <th>
12 <a href="${search.field_sort('message.raw')}">${_('Commit message')}</a>
12 <a href="${search.field_sort('message')}">${_('Commit message')}</a>
13 13 </th>
14 14 <th>
15 <a href="${search.field_sort('date')}">${_('Age')}</a>
15 <a href="${search.field_sort('date')}">${_('Commit date')}</a>
16 16 </th>
17 17 <th>
18 <a href="${search.field_sort('author.email.raw')}">${_('Author')}</a>
18 <a href="${search.field_sort('author_email')}">${_('Author')}</a>
19 19 </th>
20 20 </tr>
21 21 %for entry in c.formatted_results:
@@ -6,7 +6,7 b''
6 6 <tr>
7 7 <th>${_('Repository')}</th>
8 8 <th>
9 <a href="${search.field_sort('file.raw')}">${_('File')}</a>
9 <a href="${search.field_sort('file')}">${_('File')}</a>
10 10 </th>
11 11 <th>
12 12 <a href="${search.field_sort('size')}">${_('Size')}</a>
General Comments 0
You need to be logged in to leave comments. Login now