|
7 | 7 | from django.db import reset_queries |
8 | 8 |
|
9 | 9 | import requests |
| 10 | +from elasticutils import S as UntypedS |
10 | 11 | from elasticutils.contrib.django import S, F, get_es, ES_EXCEPTIONS # noqa |
11 | 12 | from pyelasticsearch.exceptions import ElasticHttpNotFoundError |
12 | 13 |
|
@@ -45,7 +46,37 @@ class UnindexMeBro(Exception): |
45 | 46 | pass |
46 | 47 |
|
47 | 48 |
|
48 | | -class Sphilastic(S): |
| 49 | +class AnalyzerMixin(object): |
| 50 | + |
| 51 | + def _with_analyzer(self, key, val, action): |
| 52 | + """Do a normal kind of query, with a analyzer added. |
| 53 | +
|
| 54 | + :arg key: is the field being searched |
| 55 | + :arg val: Is a two-tupe of the text to query for and the name of |
| 56 | + the analyzer to use. |
| 57 | + :arg action: is the type of query being performed, like text or |
| 58 | + text_phrase |
| 59 | + """ |
| 60 | + query, analyzer = val |
| 61 | + return { |
| 62 | + action: { |
| 63 | + key: { |
| 64 | + 'query': query, |
| 65 | + 'analyzer': analyzer, |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + def process_query_text_phrase_analyzer(self, key, val, action): |
| 71 | + """A text phrase query that includes an analyzer.""" |
| 72 | + return self._with_analyzer(key, val, 'text_phrase') |
| 73 | + |
| 74 | + def process_query_text_analyzer(self, key, val, action): |
| 75 | + """A text query that includes an analyzer.""" |
| 76 | + return self._with_analyzer(key, val, 'text') |
| 77 | + |
| 78 | + |
| 79 | +class Sphilastic(S, AnalyzerMixin): |
49 | 80 | """Shim around elasticutils.contrib.django.S. |
50 | 81 |
|
51 | 82 | Implements some Kitsune-specific behavior to make our lives |
@@ -79,6 +110,15 @@ def process_query_mlt(self, key, val, action): |
79 | 110 | } |
80 | 111 |
|
81 | 112 |
|
| 113 | +class AnalyzerS(UntypedS, AnalyzerMixin): |
| 114 | + """This is to give the search view support for setting the analyzer. |
| 115 | +
|
| 116 | + This differs from Sphilastic in that this is a plain ES S object, |
| 117 | + not based on Django. |
| 118 | + """ |
| 119 | + pass |
| 120 | + |
| 121 | + |
82 | 122 | def get_mappings(): |
83 | 123 | mappings = {} |
84 | 124 |
|
@@ -691,3 +731,24 @@ def es_analyzer_for_locale(locale, fallback="standard"): |
691 | 731 | analyzer = fallback |
692 | 732 |
|
693 | 733 | return analyzer |
| 734 | + |
| 735 | + |
| 736 | +def es_query_with_analyzer(query, locale): |
| 737 | + """Transform a query dict to use _analyzer actions for the right fields.""" |
| 738 | + analyzer = es_analyzer_for_locale(locale) |
| 739 | + new_query = {} |
| 740 | + |
| 741 | + # Import locally to avoid circular import |
| 742 | + from kitsune.search.models import get_mapping_types |
| 743 | + localized_fields = [] |
| 744 | + for mt in get_mapping_types(): |
| 745 | + localized_fields.extend(mt.get_localized_fields()) |
| 746 | + |
| 747 | + for k, v in query.items(): |
| 748 | + field, action = k.split('__') |
| 749 | + if field in localized_fields: |
| 750 | + new_query[k + '_analyzer'] = (v, analyzer) |
| 751 | + else: |
| 752 | + new_query[k] = v |
| 753 | + |
| 754 | + return new_query |
0 commit comments