Exemple #1
0
 def _create_model_filter(self, models, backend):
     """Creates a filter for the given model/queryset list."""
     from django.contrib.contenttypes.models import ContentType
     from ieltsapp.models import has_int_pk
     filters = Q()
     for model in models:
         filter = Q()
         # Process querysets.
         if isinstance(model, QuerySet):
             sub_queryset = model
             model = model.model
             queryset = sub_queryset.values_list("pk", flat=True)
             if has_int_pk(model):
                 filter &= Q(object_id_int__in=queryset, )
             else:
                 queryset = queryset.annotate(watson_pk_str=RawSQL(
                     backend.do_string_cast(
                         connections[queryset.db],
                         model._meta.pk.db_column or model._meta.pk.attname,
                     ), ()), ).values_list("watson_pk_str", flat=True)
                 filter &= Q(object_id__in=queryset, )
         # Add the model to the filter.
         content_type = ContentType.objects.get_for_model(model)
         filter &= Q(content_type=content_type, )
         # Combine with the other filters.
         filters |= filter
     return filters
Exemple #2
0
    def do_filter(self, engine_slug, queryset, search_text):
        """Performs the full text filter."""
        model = queryset.model
        content_type = ContentType.objects.get_for_model(model)
        connection = connections[queryset.db]

        pk = model._meta.pk
        if has_int_pk(model):
            ref_name = "object_id_int"
            ref_name_typecast = ""
        else:
            ref_name = "object_id"
            # Cast to text to make join work with uuid columns
            ref_name_typecast = "::text"
        return queryset.extra(
            tables=("watson_searchentry",),
            where=(
                "watson_searchentry.engine_slug = %s",
                "watson_searchentry.search_tsv @@ to_tsquery('{search_config}', %s)".format(
                    search_config=self.search_config
                ),
                "watson_searchentry.{ref_name} = {table_name}.{pk_name}{ref_name_typecast}".format(
                    ref_name=ref_name,
                    table_name=connection.ops.quote_name(model._meta.db_table),
                    pk_name=connection.ops.quote_name(pk.db_column or pk.attname),
                    ref_name_typecast=ref_name_typecast
                ),
                "watson_searchentry.content_type_id = %s"
            ),
            params=(engine_slug, self.escape_postgres_query(search_text), content_type.id),
        )
Exemple #3
0
 def do_filter(self, engine_slug, queryset, search_text):
     """Performs the full text filter."""
     model = queryset.model
     content_type = ContentType.objects.get_for_model(model)
     connection = connections[queryset.db]
     pk = model._meta.pk
     if has_int_pk(model):
         ref_name = "object_id_int"
     else:
         ref_name = "object_id"
     return queryset.extra(
         tables=("watson_searchentry",),
         where=(
             "watson_searchentry.engine_slug = %s",
             "MATCH (watson_searchentry.title, watson_searchentry.description, watson_searchentry.content) "
             "AGAINST (%s IN BOOLEAN MODE)",
             "watson_searchentry.{ref_name} = {table_name}.{pk_name}".format(
                 ref_name=ref_name,
                 table_name=connection.ops.quote_name(model._meta.db_table),
                 pk_name=connection.ops.quote_name(pk.db_column or pk.attname),
             ),
             "watson_searchentry.content_type_id = %s",
         ),
         params=(engine_slug, self._format_query(search_text), content_type.id),
     )
Exemple #4
0
    def do_filter(self, engine_slug, queryset, search_text):
        """Filters the given queryset according the the search logic for this backend."""
        model = queryset.model
        connection = connections[queryset.db]

        db_table = connection.ops.quote_name(SearchEntry._meta.db_table)
        model_db_table = connection.ops.quote_name(model._meta.db_table)
        pk = model._meta.pk
        id = connection.ops.quote_name(pk.db_column or pk.attname)
        # Add in basic filters.
        word_query = ["""
            ({db_table}.{engine_slug} = %s)
        """, """
            ({db_table}.{content_type_id} = %s)
        """]
        word_kwargs = {
            "db_table": db_table,
            "model_db_table": model_db_table,
            "engine_slug": connection.ops.quote_name("engine_slug"),
            "title": connection.ops.quote_name("title"),
            "description": connection.ops.quote_name("description"),
            "content": connection.ops.quote_name("content"),
            "content_type_id": connection.ops.quote_name("content_type_id"),
            "object_id": connection.ops.quote_name("object_id"),
            "object_id_int": connection.ops.quote_name("object_id_int"),
            "id": id,
            "iregex_operator": connection.operators["iregex"],
        }
        word_args = [
            engine_slug,
            ContentType.objects.get_for_model(model).id,
        ]
        # Add in join.
        if has_int_pk(model):
            word_query.append("""
                ({db_table}.{object_id_int} = {model_db_table}.{id})
            """)
        else:
            word_query.append("""
                ({db_table}.{object_id} = {model_db_table}.{id})
            """)
        # Add in all words.
        for word in search_text.split():
            regex = regex_from_word(word)
            word_query.append(
                """
                ({db_table}.{title} {iregex_operator}
                OR {db_table}.{description} {iregex_operator}
                OR {db_table}.{content} {iregex_operator})
                """
            )
            word_args.extend((regex, regex, regex))
        # Compile the query.
        full_word_query = " AND ".join(word_query).format(**word_kwargs)
        return queryset.extra(
            tables=(db_table,),
            where=(full_word_query,),
            params=word_args,
        )
Exemple #5
0
 def _get_entries_for_obj(self, obj):
     """Returns a queryset of entries associate with the given obj."""
     from django.contrib.contenttypes.models import ContentType
     from ieltsapp.models import SearchEntry, has_int_pk, get_str_pk
     model = obj.__class__
     content_type = ContentType.objects.get_for_model(model)
     # Get the basic list of search entries.
     search_entries = SearchEntry.objects.filter(
         content_type=content_type,
         engine_slug=self._engine_slug,
     )
     object_id = get_str_pk(obj, connections[search_entries.db])
     if has_int_pk(model):
         # Do a fast indexed lookup.
         object_id_int = int(obj.pk)
         search_entries = search_entries.filter(
             object_id_int=object_id_int, )
     else:
         # Alas, have to do a slow unindexed lookup.
         object_id_int = None
         search_entries = search_entries.filter(object_id=object_id, )
     return object_id_int, search_entries