diff options
Diffstat (limited to 'ishtar_common/models.py')
| -rw-r--r-- | ishtar_common/models.py | 135 | 
1 files changed, 92 insertions, 43 deletions
| diff --git a/ishtar_common/models.py b/ishtar_common/models.py index f802b434c..959c31a1f 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1294,7 +1294,6 @@ class JsonData(models.Model, CachedGen):          return choices -  class Imported(models.Model):      imports = models.ManyToManyField(          Import, blank=True, @@ -1352,6 +1351,23 @@ class DynamicRequest(object):          return alt_names +class SearchVectorConfig(object): +    def __init__(self, key, language=None, func=None): +        self.key = key +        if language: +            self.language = language +            if language == "local": +                self.language = settings.ISHTAR_SEARCH_LANGUAGE +        else: +            self.language = "simple" +        self.func = func + +    def format(self, value): +        if not self.func: +            return [value] +        return self.func(value) + +  class FullSearch(models.Model):      search_vector = SearchVectorField(_("Search vector"), blank=True, null=True,                                        help_text=_("Auto filled at save")) @@ -1398,6 +1414,17 @@ class FullSearch(models.Model):                  deactivate()          return query_parameters +    def _update_search_field(self, search_vector_conf, search_vectors, data): +        for value in search_vector_conf.format(data): +            with connection.cursor() as cursor: +                cursor.execute("SELECT to_tsvector(%s, %s)", [ +                    search_vector_conf.language, value]) +                row = cursor.fetchone() +                search_vectors.append(row[0]) + +    def _update_search_number_field(self, search_vectors, val): +        search_vectors.append("'{}':1".format(val)) +      def update_search_vector(self, save=True, exclude_parent=False):          """          Update the search vector @@ -1428,25 +1455,25 @@ class FullSearch(models.Model):          base_q = self.__class__.objects.filter(pk=self.pk)          # many to many have to be queried one by one otherwise only one is fetch -        for M2M_SEARCH_VECTOR in self.M2M_SEARCH_VECTORS: -            key = M2M_SEARCH_VECTOR.split('__')[0] +        for m2m_search_vector in self.M2M_SEARCH_VECTORS: +            key = m2m_search_vector.key.split('__')[0]              rel_key = getattr(self, key)              for item in rel_key.values('pk').all(): -                for lang in ("simple", settings.ISHTAR_SEARCH_LANGUAGE): -                    query_dct = {key + "__pk": item['pk']} -                    q = copy.copy(base_q).filter(**query_dct) -                    q = q.annotate( -                        search=SearchVector( -                            M2M_SEARCH_VECTOR, -                            config=lang) -                    ).values('search') -                    search_vectors.append(q.all()[0]['search']) +                query_dct = {key + "__pk": item['pk']} +                q = copy.copy(base_q).filter(**query_dct) +                q = q.annotate( +                    search=SearchVector( +                        m2m_search_vector.key, +                        config=m2m_search_vector.language) +                ).values('search') +                search_vectors.append(q.all()[0]['search'])          # int/float are not well managed by the SearchVector -        for INT_SEARCH_VECTOR in self.INT_SEARCH_VECTORS: -            q = base_q.values(INT_SEARCH_VECTOR) -            search_vectors.append( -                "'{}':1".format(q.all()[0][INT_SEARCH_VECTOR])) +        for int_search_vector in self.INT_SEARCH_VECTORS: +            q = base_q.values(int_search_vector.key) +            for val in int_search_vector.format( +                    q.all()[0][int_search_vector.key]): +                self._update_search_number_field(search_vectors, val)          if not exclude_parent:              # copy parent vector fields @@ -1472,32 +1499,24 @@ class FullSearch(models.Model):          if self.BASE_SEARCH_VECTORS:              # query "simple" fields -            q = base_q.values(*self.BASE_SEARCH_VECTORS) +            q = base_q.values(*[sv.key for sv in self.BASE_SEARCH_VECTORS])              res = q.all()[0]              for base_search_vector in self.BASE_SEARCH_VECTORS: -                data = res[base_search_vector] +                data = res[base_search_vector.key]                  data = unidecode(unicode(data)) -                for lang in ("simple", settings.ISHTAR_SEARCH_LANGUAGE): -                    with connection.cursor() as cursor: -                        cursor.execute("SELECT to_tsvector(%s, %s)", -                                       [lang, data]) -                        row = cursor.fetchone() -                        search_vectors.append(row[0]) +                self._update_search_field(base_search_vector, +                                          search_vectors, data)          if self.PROPERTY_SEARCH_VECTORS: -            for attr in self.PROPERTY_SEARCH_VECTORS: -                data = getattr(self, attr) +            for property_search_vector in self.PROPERTY_SEARCH_VECTORS: +                data = getattr(self, property_search_vector.key)                  if callable(data):                      data = data()                  if not data:                      continue                  data = unicode(data) -                for lang in ("simple", settings.ISHTAR_SEARCH_LANGUAGE): -                    with connection.cursor() as cursor: -                        cursor.execute("SELECT to_tsvector(%s, %s)", -                                       [lang, data]) -                        row = cursor.fetchone() -                        search_vectors.append(row[0]) +                self._update_search_field(property_search_vector, +                                          search_vectors, data)          if hasattr(self, 'data') and self.data:              content_type = ContentType.objects.get_for_model(self) @@ -1511,7 +1530,20 @@ class FullSearch(models.Model):                          no_data = True                          break                      data = data[key] -                if no_data: +                if no_data or not data: +                    continue + +                if json_field.value_type == 'B': +                    if data is True: +                        data = json_field.name +                    else: +                        continue +                elif json_field.value_type in ('I', 'F'): +                    self._update_search_number_field(search_vectors, data) +                    continue +                elif json_field.value_type == 'D': +                    # only index year +                    self._update_search_number_field(search_vectors, data.year)                      continue                  for lang in ("simple", settings.ISHTAR_SEARCH_LANGUAGE):                      with connection.cursor() as cursor: @@ -3430,7 +3462,8 @@ class Organization(Address, Merge, OwnPerms, ValueGetter):      # search parameters      EXTRA_REQUEST_KEYS = {} -    BASE_SEARCH_VECTORS = ['name', 'town'] +    BASE_SEARCH_VECTORS = [SearchVectorConfig('name'), +                           SearchVectorConfig('town')]      # alternative names of fields for searches      ALT_NAMES = { @@ -3564,8 +3597,13 @@ class Person(Address, Merge, OwnPerms, ValueGetter):                            'profiles_list', 'attached_to', 'town')      SHOW_URL = 'show-person'      MODIFY_URL = 'person_modify' -    BASE_SEARCH_VECTORS = ['name', 'surname', 'raw_name', 'town', -                           'attached_to__name', 'email'] +    BASE_SEARCH_VECTORS = [ +        SearchVectorConfig('name'), +        SearchVectorConfig('surname'), +        SearchVectorConfig('raw_name'), +        SearchVectorConfig('town'), +        SearchVectorConfig('attached_to__name'), +        SearchVectorConfig('email')]      # search parameters      REVERSED_BOOL_FIELDS = ['ishtaruser__isnull'] @@ -3965,8 +4003,12 @@ class IshtarUser(FullSearch):                    'person__email', 'person__person_types_list',                    'person__attached_to__name')      BASE_SEARCH_VECTORS = [ -        'user_ptr__username', 'person__name', 'person__surname', -        'person__email', 'person__town', 'person__attached_to__name'] +        SearchVectorConfig('user_ptr__username'), +        SearchVectorConfig('person__name'), +        SearchVectorConfig('person__surname'), +        SearchVectorConfig('person__email'), +        SearchVectorConfig('person__town'), +        SearchVectorConfig('person__attached_to__name')]      # search parameters      EXTRA_REQUEST_KEYS = { @@ -4109,8 +4151,9 @@ class Basket(FullSearch, OwnPerms):      TABLE_COLS = ['label', 'user'] -    BASE_SEARCH_VECTORS = ['label', 'comment'] -    M2M_SEARCH_VECTORS = ['items'] +    BASE_SEARCH_VECTORS = [ +        SearchVectorConfig('label'), SearchVectorConfig('comment', 'local')] +    M2M_SEARCH_VECTORS = [SearchVectorConfig('items')]      class Meta:          abstract = True @@ -4320,9 +4363,15 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel):                    'authors__cached_label',                    'associated_url']      COL_LINK = ['associated_url'] -    BASE_SEARCH_VECTORS = ['title', 'source_type__label', 'external_id', -                           'reference', 'description', 'comment', -                           'additional_information'] +    BASE_SEARCH_VECTORS = [ +        SearchVectorConfig("title"), +        SearchVectorConfig("source_type__label"), +        SearchVectorConfig("external_id"), +        SearchVectorConfig("reference"), +        SearchVectorConfig("description", "local"), +        SearchVectorConfig("comment", "local"), +        SearchVectorConfig("additional_information", "local"), +    ]      PARENT_SEARCH_VECTORS = ['authors', ]      BOOL_FIELDS = ['duplicate'] | 
