예제 #1
0
def default_home_context_processor(context):
    recent_datasets, recent_reuses = search.multiquery(
        search.SearchQuery(Dataset, sort='-created', page_size=12),
        search.SearchQuery(Reuse, sort='-created', page_size=12),
    )
    context.update(recent_datasets=recent_datasets,
                   recent_reuses=recent_reuses)
    return context
예제 #2
0
파일: views.py 프로젝트: guillo-w/udata
def render_search():
    params = multi_to_dict(request.args)
    params['facets'] = True
    datasets, organizations, reuses, users = search.multiquery(
        search.SearchQuery(Dataset, **params),
        search.SearchQuery(Organization, **params),
        search.SearchQuery(Reuse, **params),
        search.SearchQuery(User, **params),
    )
    return theme.render('search.html',
                        datasets=datasets,
                        organizations=organizations,
                        reuses=reuses,
                        users=users)
예제 #3
0
def render_search():
    params = multi_to_dict(request.args)
    params['facets'] = True
    # We only fetch relevant data for the given filter.
    if 'tag' in params:
        search_queries = [
            search.SearchQuery(Dataset, **params),
            search.SearchQuery(Reuse, **params)
        ]
        results_labels = ['datasets', 'reuses']
    elif 'badge' in params:
        search_queries = [
            search.SearchQuery(Dataset, **params),
            search.SearchQuery(Organization, **params)
        ]
        results_labels = ['datasets', 'organizations']
    else:
        search_queries = [
            search.SearchQuery(Dataset, **params),
            search.SearchQuery(Reuse, **params),
            search.SearchQuery(Organization, **params),
            search.SearchQuery(User, **params)
        ]
        results_labels = ['datasets', 'reuses', 'organizations', 'users']
    results = search.multiquery(*search_queries)
    context = dict(zip(results_labels, results))
    context['territories'] = check_for_territories(params.get('q'))
    return theme.render('search.html', **context)
예제 #4
0
    def test_facet_filter_extras(self):
        search_query = search.SearchQuery(
            FakeSearch, **{
                'q': 'test',
                'extra.key': 'value'
            })
        expectations = [
            {
                'multi_match': {
                    'query': 'test',
                    'analyzer': search.i18n_analyzer,
                    'type': 'cross_fields',
                    'fields': ['title^2', 'description']
                }
            },
            {
                'term': {
                    'extras.key': 'value'
                }
            },
        ]

        query = search_query.get_query()
        self.assertEqual(len(query['bool']['must']), len(expectations))
        for expected in expectations:
            self.assertIn(expected, query['bool']['must'])
예제 #5
0
 def test_iterate(self):
     with self.autoindex():
         objects = [FakeFactory() for _ in range(5)]
     query = search.SearchQuery(FakeSearch)
     for idx, obj in enumerate(query.iter(), 1):
         self.assertIsInstance(obj, Fake)
     self.assertEqual(idx, len(objects))
예제 #6
0
 def test_empty_search(self):
     '''An empty query should match all documents'''
     search_query = search.SearchQuery(FakeSearch)
     body = search_query.get_body()
     self.assertEqual(body['query'], {'match_all': {}})
     self.assertEqual(body['facets'], {})
     self.assertEqual(body['sort'], [])
예제 #7
0
 def test_paginated_search(self):
     '''Search should handle pagination'''
     search_query = search.SearchQuery(FakeSearch, page=3, page_size=10)
     body = search_query.get_body()
     self.assertIn('from', body)
     self.assertEqual(body['from'], 20)
     self.assertIn('size', body)
     self.assertEqual(body['size'], 10)
예제 #8
0
    def test_no_pagination_in_query(self):
        '''Search results should be paginated even if not asked'''
        query = search.SearchQuery(FakeSearch)
        result = search.SearchResult(query, {})

        self.assertEqual(result.page, 1),
        self.assertEqual(result.page_size, search.DEFAULT_PAGE_SIZE)
        self.assertEqual(result.pages, 0)
예제 #9
0
    def test_pagination_empty(self):
        '''Search results should be paginated even if empty'''
        query = search.SearchQuery(FakeSearch, page=2, page_size=3)
        result = search.SearchResult(query, {})

        self.assertEqual(result.page, 1),
        self.assertEqual(result.page_size, 3)
        self.assertEqual(result.pages, 0)
예제 #10
0
    def test_pagination(self):
        '''Search results should be paginated'''
        kwargs = {'page': 2, 'page_size': 3}
        query = search.SearchQuery(FakeSearch, **kwargs)
        result = search.SearchResult(query, es_factory(nb=3, total=11))

        self.assertEqual(result.page, 2),
        self.assertEqual(result.page_size, 3)
        self.assertEqual(result.pages, 4)
예제 #11
0
 def test_selected_facets(self):
     selected_facets = ['tag', 'other']
     search_query = search.SearchQuery(FakeSearch, facets=selected_facets)
     facets = search_query.get_facets()
     self.assertEqual(len(facets), len(selected_facets))
     for key in FakeSearch.facets.keys():
         if key in selected_facets:
             self.assertIn(key, facets.keys())
         else:
             self.assertNotIn(key, facets.keys())
예제 #12
0
    def test_no_failures(self):
        '''Search result should not fail on missing properties'''
        query = search.SearchQuery(FakeSearch)
        result = search.SearchResult(query, {})

        self.assertEqual(result.total, 0)
        self.assertEqual(result.max_score, 0)

        ids = result.get_ids()
        self.assertEqual(len(ids), 0)
예제 #13
0
    def test_properties(self):
        '''Search result should map some properties for easy access'''
        response = es_factory(nb=10, total=42)
        max_score = response['hits']['max_score']
        query = search.SearchQuery(FakeSearch)
        result = search.SearchResult(query, response)

        self.assertEqual(result.total, 42)
        self.assertEqual(result.max_score, max_score)

        ids = result.get_ids()
        self.assertEqual(len(ids), 10)
예제 #14
0
    def test_custom_function_scoring(self):
        '''Search should handle field boosting by function'''
        class FakeBoostedSearch(FakeSearch):
            boosters = [search.FunctionBooster('doc["field"].value * 2')]

        query = search.SearchQuery(FakeBoostedSearch)
        body = query.get_body()
        # Query should be wrapped in function_score
        self.assertEqual(body['query']['function_score']['functions'][0], {
            'script_score': {
                'script': 'doc["field"].value * 2'
            },
        })
예제 #15
0
 def test_multi_sorted_search(self):
     '''Search should sort'''
     search_query = search.SearchQuery(FakeSearch,
                                       sort=['-title', 'description'])
     body = search_query.get_body()
     self.assertEqual(body['sort'], [
         {
             'title.raw': 'desc'
         },
         {
             'description.raw': 'asc'
         },
     ])
예제 #16
0
 def test_facet_filter_multi(self):
     search_query = search.SearchQuery(FakeSearch,
                                       q='test',
                                       tag=['value-1', 'value-2'],
                                       other='value',
                                       range='3-8',
                                       daterange='2013-01-07-2014-06-07')
     expectations = [
         {
             'multi_match': {
                 'query': 'test',
                 'analyzer': search.i18n_analyzer,
                 'type': 'cross_fields',
                 'fields': ['title^2', 'description']
             }
         },
         {
             'term': {
                 'tags': 'value-1'
             }
         },
         {
             'term': {
                 'tags': 'value-2'
             }
         },
         {
             'term': {
                 'other': 'value'
             }
         },
         {
             'range': {
                 'a_num_field': {
                     'gte': 3,
                     'lte': 8,
                 }
             }
         },
         {
             'range': {
                 'a_daterange_field': {
                     'lte': '2014-06-07',
                     'gte': '2013-01-07',
                 },
             }
         },
     ]
     query = search_query.get_query()
     for expected in expectations:
         self.assertIn(expected, query['bool']['must'])
예제 #17
0
    def test_decay_function_scoring_with_options(self):
        '''Search should handle field decay with options'''
        class FakeBoostedSearch(FakeSearch):
            boosters = [
                search.GaussDecay('a_num_field', 10, 20, offset=5, decay=0.5),
                search.ExpDecay('another_field',
                                20,
                                scale=30,
                                offset=5,
                                decay=0.5),
                search.LinearDecay('last_field', 30, 40, offset=5, decay=0.5),
            ]

        query = search.SearchQuery(FakeBoostedSearch)
        body = query.get_body()
        functions = body['query']['function_score']['functions']
        # Query should be wrapped in a gaus decay function
        self.assertEqual(
            functions[0], {
                'gauss': {
                    'a_num_field': {
                        'origin': 10,
                        'scale': 20,
                        'offset': 5,
                        'decay': 0.5,
                    }
                },
            })
        self.assertEqual(
            functions[1], {
                'exp': {
                    'another_field': {
                        'origin': 20,
                        'scale': 30,
                        'offset': 5,
                        'decay': 0.5,
                    }
                },
            })
        self.assertEqual(
            functions[2], {
                'linear': {
                    'last_field': {
                        'origin': 30,
                        'scale': 40,
                        'offset': 5,
                        'decay': 0.5
                    }
                },
            })
예제 #18
0
 def test_simple_excluding_query(self):
     '''A simple query should negate a simple term in query_string'''
     search_query = search.SearchQuery(FakeSearch, q='-test')
     expected = {
         'bool': {
             'must_not': [{
                 'multi_match': {
                     'query': 'test',
                     'analyzer': search.i18n_analyzer,
                     'type': 'cross_fields',
                     'fields': ['title^2', 'description']
                 }
             }]
         }
     }
     self.assertEqual(search_query.get_query(), expected)
예제 #19
0
 def test_simple_query_flatten(self):
     '''A simple query should use query_string with specified fields and should flatten'''
     search_query = search.SearchQuery(FakeSearch, q='test')
     expected = {
         'bool': {
             'must': [{
                 'multi_match': {
                     'query': 'test',
                     'analyzer': search.i18n_analyzer,
                     'type': 'cross_fields',
                     'fields': ['title^2', 'description']
                 }
             }]
         }
     }
     self.assertEqual(search_query.get_query(), expected)
예제 #20
0
    def test_to_url_with_none(self):
        kwargs = {
            'q': 'test',
            'tag': ['tag1', 'tag2'],
            'page': 2,
        }
        search_query = search.SearchQuery(FakeSearch, **kwargs)
        with self.app.test_request_context('/an_url'):
            url = search_query.to_url(tag=None, other='value', replace=True)
        parsed_url = url_parse(url)
        qs = url_decode(parsed_url.query)

        self.assertEqual(parsed_url.path, '/an_url')
        self.assertEqual(multi_to_dict(qs), {
            'q': 'test',
            'other': 'value',
        })
예제 #21
0
    def test_to_url_with_specified_url(self):
        kwargs = {
            'q': 'test',
            'tag': ['tag1', 'tag2'],
            'page': 2,
        }
        search_query = search.SearchQuery(FakeSearch, **kwargs)
        with self.app.test_request_context('/an_url'):
            url = search_query.to_url('/another_url')
        parsed_url = url_parse(url)
        qs = url_decode(parsed_url.query)

        self.assertEqual(parsed_url.path, '/another_url')
        self.assertEqual(multi_to_dict(qs), {
            'q': 'test',
            'tag': ['tag1', 'tag2'],
            'page': '2',
        })
예제 #22
0
 def test_simple_query_fuzzy(self):
     '''A simple query should use query_string with specified fields'''
     search_query = search.SearchQuery(FuzzySearch, q='test')
     expected = {
         'bool': {
             'must': [{
                 'multi_match': {
                     'query': 'test',
                     'analyzer': search.i18n_analyzer,
                     'type': 'cross_fields',
                     'fields': ['title^2', 'description'],
                     'fuzziness': 'AUTO',
                     'prefix_length': 2,
                 }
             }]
         }
     }
     self.assertEqual(search_query.get_query(), expected)
예제 #23
0
    def test_custom_scoring(self):
        '''Search should handle field boosting'''
        class FakeBoostedSearch(FakeSearch):
            boosters = [search.BoolBooster('some_bool_field', 1.1)]

        query = search.SearchQuery(FakeBoostedSearch)
        body = query.get_body()
        # Query should be wrapped in function_score
        self.assertIn('function_score', body['query'])
        self.assertIn('query', body['query']['function_score'])
        self.assertIn('functions', body['query']['function_score'])
        self.assertEqual(body['query']['function_score']['functions'][0], {
            'filter': {
                'term': {
                    'some_bool_field': True
                }
            },
            'boost_factor': 1.1,
        })
예제 #24
0
    def test_default_type(self):
        '''Default analyzer is overridable'''
        class FakeAnalyzerSearch(FakeSearch):
            match_type = 'most_fields'

        search_query = search.SearchQuery(FakeAnalyzerSearch, q='test')
        expected = {
            'bool': {
                'must': [{
                    'multi_match': {
                        'query': 'test',
                        'analyzer': search.i18n_analyzer,
                        'type': 'most_fields',
                        'fields': ['title^2', 'description']
                    }
                }]
            }
        }
        self.assertEqual(search_query.get_query(), expected)
예제 #25
0
 def test_query_with_both_including_and_excluding_terms(self):
     '''A simple query should detect negation on each term in query_string'''
     search_query = search.SearchQuery(FakeSearch, q='test -negated')
     expected = {
         'bool': {
             'must': [{
                 'multi_match': {
                     'query': 'test',
                     'analyzer': search.i18n_analyzer,
                     'type': 'cross_fields',
                     'fields': ['title^2', 'description']
                 }
             }],
             'must_not': [{
                 'multi_match': {
                     'query': 'negated',
                     'analyzer': search.i18n_analyzer,
                     'type': 'cross_fields',
                     'fields': ['title^2', 'description']
                 }
             }]
         }
     }
     self.assertEqual(search_query.get_query(), expected)
예제 #26
0
    def test_decay_function_scoring_with_callables(self):
        '''Search should handle field decay with options'''
        get_dot5 = lambda: 0.5  # noqa
        get_5 = lambda: 5  # noqa
        get_10 = lambda: 10  # noqa
        get_20 = lambda: 20  # noqa
        get_30 = lambda: 30  # noqa
        get_40 = lambda: 40  # noqa

        class FakeBoostedSearch(FakeSearch):
            boosters = [
                search.GaussDecay('a_num_field',
                                  get_10,
                                  get_20,
                                  offset=get_5,
                                  decay=get_dot5),
                search.ExpDecay('another_field',
                                get_20,
                                scale=get_30,
                                offset=get_5,
                                decay=get_dot5),
                search.LinearDecay('last_field',
                                   get_30,
                                   get_40,
                                   offset=get_5,
                                   decay=get_dot5),
            ]

        query = search.SearchQuery(FakeBoostedSearch)
        body = query.get_body()
        functions = body['query']['function_score']['functions']
        # Query should be wrapped in a gaus decay function
        self.assertEqual(
            functions[0], {
                'gauss': {
                    'a_num_field': {
                        'origin': 10,
                        'scale': 20,
                        'offset': 5,
                        'decay': 0.5,
                    }
                },
            })
        self.assertEqual(
            functions[1], {
                'exp': {
                    'another_field': {
                        'origin': 20,
                        'scale': 30,
                        'offset': 5,
                        'decay': 0.5,
                    }
                },
            })
        self.assertEqual(
            functions[2], {
                'linear': {
                    'last_field': {
                        'origin': 30,
                        'scale': 40,
                        'offset': 5,
                        'decay': 0.5
                    }
                },
            })
예제 #27
0
 def test_sorted_search_asc(self):
     '''Search should sort by field in ascending order'''
     search_query = search.SearchQuery(FakeSearch, sort='title')
     body = search_query.get_body()
     self.assertEqual(body['sort'], [{'title.raw': 'asc'}])
예제 #28
0
 def test_iterate_empty(self):
     with self.autoindex():
         [FakeFactory() for _ in range(5)]
     query = search.SearchQuery(FakeSearch, tag='not-found')
     self.assertEqual(len(list(query.iter())), 0)
예제 #29
0
 def test_facets(self):
     search_query = search.SearchQuery(FakeSearch, facets=True)
     facets = search_query.get_facets()
     self.assertEqual(len(facets), len(FakeSearch.facets))
     for key in FakeSearch.facets.keys():
         self.assertIn(key, facets.keys())