Merge lp:~rharding/charmworld/apply-cowboys into lp:charmworld

Proposed by Richard Harding
Status: Merged
Approved by: Richard Harding
Approved revision: 490
Merged at revision: 494
Proposed branch: lp:~rharding/charmworld/apply-cowboys
Merge into: lp:charmworld
Diff against target: 114 lines (+11/-24)
4 files modified
charmworld/search.py (+8/-11)
charmworld/tests/test_search.py (+0/-9)
charmworld/views/api/__init__.py (+1/-3)
charmworld/views/search.py (+2/-1)
To merge this branch: bzr merge lp:~rharding/charmworld/apply-cowboys
Reviewer Review Type Date Requested Status
Juju Gui Bot continuous-integration Approve
Richard Harding Approve
Benji York (community) code Approve
Review via email: mp+211517@code.launchpad.net

Commit message

Update scoring to be limited on ES side.

- Drive-by to make sure we log the exception from ES for debugging purposes.

Description of the change

Update scoring to be limited on ES side.

- Drive-by to make sure we log the exception from ES for debugging purposes.

To post a comment you must log in.
Revision history for this message
Benji York (benji) wrote :

There is a nice alternative to log.error(str(exc)) in the logging
package: log.exception()

If the logging is important, we should have tests to ensure it keeps
working.

If the default value for min_score were set to MIN_ES_SCORE then we
wouldn't need the inline-if expression to set if no value was provided.

review: Approve (code)
Revision history for this message
Richard Harding (rharding) wrote :

> There is a nice alternative to log.error(str(exc)) in the logging
> package: log.exception()

Thanks, will update.

> If the default value for min_score were set to MIN_ES_SCORE then we
> wouldn't need the inline-if expression to set if no value was provided.

I originally did this, but the caller would end up passing in a None value which would reset the default. So I did this instead to make sure you can adjust the min score, but you can't leave it None if you're not fetching all explicitly.

490. By Richard Harding

Update per review

Revision history for this message
Richard Harding (rharding) :
review: Approve
Revision history for this message
Juju Gui Bot (juju-gui-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmworld/search.py'
--- charmworld/search.py 2014-03-12 19:22:56 +0000
+++ charmworld/search.py 2014-03-18 15:21:03 +0000
@@ -20,6 +20,8 @@
20 Timer,20 Timer,
21)21)
2222
23MIN_ES_SCORE = 0.5
24
23# Where wildcards are used, the final var name must be used, to avoid25# Where wildcards are used, the final var name must be used, to avoid
24# selecting any fields that may be integers, such as config.options.*.default,26# selecting any fields that may be integers, such as config.options.*.default,
25# provides.*.interface.limit, or changes.revno. Selecting an integer field27# provides.*.interface.limit, or changes.revno. Selecting an integer field
@@ -553,7 +555,7 @@
553 def api_search(self, text='', filters=None, type_=None,555 def api_search(self, text='', filters=None, type_=None,
554 limit=None, valid_only=True, sort=None,556 limit=None, valid_only=True, sort=None,
555 autocomplete=False, doctype=CHARM,557 autocomplete=False, doctype=CHARM,
556 min_score=1.0):558 min_score=None):
557 """Search charms and bundles (as used by the API).559 """Search charms and bundles (as used by the API).
558560
559 :param text: A string to search for -- will be analyzed (i.e. split561 :param text: A string to search for -- will be analyzed (i.e. split
@@ -606,7 +608,12 @@
606 elif sort is not None:608 elif sort is not None:
607 raise ValueError('Invalid sort: %s.' % sort)609 raise ValueError('Invalid sort: %s.' % sort)
608610
611 # Make sure we always get scores back from ES.
612 dsl['track_scores'] = True
613
609 if not all_requested:614 if not all_requested:
615 min_score = min_score if min_score is not None else MIN_ES_SCORE
616 dsl['min_score'] = min_score
610 if limit is None:617 if limit is None:
611 limit = self.default_search_limit618 limit = self.default_search_limit
612 else:619 else:
@@ -617,20 +624,10 @@
617 except ElasticHttpError:624 except ElasticHttpError:
618 hits = []625 hits = []
619626
620 # Sorted queries do not return scores, so don't filter if we have a
621 # sort.
622 if not all_requested and sort is None:
623 hits = self._filter_by_score(hits, min_score)
624
625 return [627 return [
626 dict(doctype=hit['_type'], data=hit['_source']['data'])628 dict(doctype=hit['_type'], data=hit['_source']['data'])
627 for hit in hits]629 for hit in hits]
628630
629 @staticmethod
630 def _filter_by_score(results, min_score):
631 """Filter the results by a minimum score."""
632 return [res for res in results if res['_score'] >= min_score]
633
634 def get_status(self):631 def get_status(self):
635 with translate_error():632 with translate_error():
636 return self._client.status(index=self.index_name)['indices']633 return self._client.status(index=self.index_name)['indices']
637634
=== modified file 'charmworld/tests/test_search.py'
--- charmworld/tests/test_search.py 2014-03-12 19:22:56 +0000
+++ charmworld/tests/test_search.py 2014-03-18 15:21:03 +0000
@@ -5,7 +5,6 @@
55
66
7from datetime import datetime7from datetime import datetime
8import random
9from textwrap import dedent8from textwrap import dedent
10from time import sleep9from time import sleep
1110
@@ -684,14 +683,6 @@
684 result = self.index_client.api_search('charms', {}, None)683 result = self.index_client.api_search('charms', {}, None)
685 self.assertEqual(22, len(result))684 self.assertEqual(22, len(result))
686685
687 def test_filter_by_score(self):
688 hits = [{'_score': i} for i in xrange(10)]
689 random.shuffle(hits)
690 cutoff = 4
691 filtered = self.index_client._filter_by_score(hits, cutoff)
692 for item in filtered:
693 self.assertTrue(item['_score'] >= cutoff)
694
695 def test_api_search_with_store_error(self):686 def test_api_search_with_store_error(self):
696 """api_search() does not return charms withs errors by default."""687 """api_search() does not return charms withs errors by default."""
697 self.makeCharm(name='evil-charm', charm_error=True)688 self.makeCharm(name='evil-charm', charm_error=True)
698689
=== modified file 'charmworld/views/api/__init__.py'
--- charmworld/views/api/__init__.py 2014-03-12 19:22:56 +0000
+++ charmworld/views/api/__init__.py 2014-03-18 15:21:03 +0000
@@ -720,9 +720,7 @@
720 if key in ('series', 'owner', 'name', 'categories'))720 if key in ('series', 'owner', 'name', 'categories'))
721 if text is None:721 if text is None:
722 text = ['']722 text = ['']
723 if min_score is None:723 if min_score is not None:
724 min_score = 1
725 else:
726 min_score = float(min_score[0])724 min_score = float(min_score[0])
727 params['i_provides'] = provides725 params['i_provides'] = provides
728 params['i_requires'] = requires726 params['i_requires'] = requires
729727
=== modified file 'charmworld/views/search.py'
--- charmworld/views/search.py 2013-11-15 20:02:03 +0000
+++ charmworld/views/search.py 2014-03-18 15:21:03 +0000
@@ -31,10 +31,11 @@
31 request=request)31 request=request)
32 response.status_code = 50332 response.status_code = 503
33 return response33 return response
34 except ElasticHttpError:34 except ElasticHttpError as exc:
35 text = request.params["search_text"]35 text = request.params["search_text"]
36 log.warning(36 log.warning(
37 "User search error with search text='{}'".format(text))37 "User search error with search text='{}'".format(text))
38 log.exception(exc)
38 response = render_to_response(39 response = render_to_response(
39 '../templates/search-terms-bad.pt',40 '../templates/search-terms-bad.pt',
40 {'search_text': text},41 {'search_text': text},

Subscribers

People subscribed via source and target branches

to all changes: