夹层 CMS 中的缓慢搜索

Slow Search in Mezzanine CMS

夹层 CMS 中的搜索速度较慢。我使用夹层 CMS。我发现它在搜索某些东西时太慢了。 blog_blogpost 的大小约为 60,000 条记录。

示例站点是 www.chinalaw.vip

请帮忙!

这是由不区分大小写的匹配项(图标包含)和没有任何索引引起的。我通过以下步骤解决问题:

1、将不区分大小写的匹配更改为夹层中区分大小写的匹配

    excluded = [reduce(iand, [~Q(**{"%s__contains" % f: t[1:]}) for f in
        self._search_fields.keys()]) for t in terms if t[0:1] == "-"]
    required = [reduce(ior, [Q(**{"%s__contains" % f: t[1:]}) for f in
        self._search_fields.keys()]) for t in terms if t[0:1] == "+"]
    optional = [reduce(ior, [Q(**{"%s__contains" % f: t}) for f in
        self._search_fields.keys()]) for t in terms if t[0:1] not in "+-"]

2、将django中路径django\contrib\admin\options.py中的不区分大小写的匹配改为区分大小写的匹配。

def get_search_results(self, request, queryset, search_term):
    """
    Return a tuple containing a queryset to implement the search
    and a boolean indicating if the results may contain duplicates.
    """
    # Apply keyword searches.
    def construct_search(field_name):
        if field_name.startswith('^'):
            return "%s__istartswith" % field_name[1:]
        elif field_name.startswith('='):
            return "%s__iexact" % field_name[1:]
        elif field_name.startswith('@'):
            return "%s__search" % field_name[1:]
        # Use field_name if it includes a lookup.
        opts = queryset.model._meta
        lookup_fields = field_name.split(LOOKUP_SEP)
        # Go through the fields, following all relations.
        prev_field = None
        for path_part in lookup_fields:
            if path_part == 'pk':
                path_part = opts.pk.name
            try:
                field = opts.get_field(path_part)
            except FieldDoesNotExist:
                # Use valid query lookups.
                if prev_field and prev_field.get_lookup(path_part):
                    return field_name
            else:
                prev_field = field
                if hasattr(field, 'get_path_info'):
                    # Update opts to follow the relation.
                    opts = field.get_path_info()[-1].to_opts
        # Otherwise, use the field with icontains.
        return "%s__contains" % field_name

    use_distinct = False
    search_fields = self.get_search_fields(request)
    if search_fields and search_term:
        orm_lookups = [construct_search(str(search_field))
                       for search_field in search_fields]
        for bit in search_term.split():
            or_queries = [models.Q(**{orm_lookup: bit})
                          for orm_lookup in orm_lookups]
            queryset = queryset.filter(reduce(operator.or_, or_queries))
        use_distinct |= any(lookup_needs_distinct(self.opts, search_spec) for search_spec in orm_lookups)

    return queryset, use_distinct

3、创建索引

   CREATE EXTENSION pg_trgm;

   CREATE INDEX blog_blogpost_content_index ON blog_blogpost USING gin (title gin_trgm_ops,description gin_trgm_ops,content gin_trgm_ops,keywords_string  gin_trgm_ops);