Django中的全文搜索(Full Text Search)框架与其它搜索引擎的比较

2023-04-11 00:00:00 框架 搜索引擎 全文

Django提供了内置的全文搜索框架,称为Django全文搜索(Django Full Text Search)。然而,Django全文搜索并不是一款完整的搜索引擎,而是提供了一些类似于SQL查询的功能。

相比于其它搜索引擎,Django全文搜索框架的优势在于其轻量级和易于使用。它依赖于数据库的全文搜索功能,因此需要使用支持全文搜索的数据库。目前,Django支持的数据库包括MySQL、PostgreSQL和SQLite,并且所有这些数据库都支持全文搜索。

以下是使用Django全文搜索框架实现搜索功能的示例代码:

首先,在models.py文件中,定义一个模型类,并使用django.contrib.postgres中的SearchVectorField来存储全文搜索的结果:

from django.contrib.postgres.search import SearchVectorField

class Blog(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    search_vector = SearchVectorField(null=True, blank=True)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        Blog.objects.filter(id=self.id).update(search_vector=(
            SearchVector('title', weight='A') + SearchVector('content', weight='B')
        ))

在管理员页面中,我们需要配置搜索字段和显示字段,并使用SearchQuery和SearchRank来实现搜索和排名:

from django.contrib.postgres.search import (
    SearchQuery, SearchRank, SearchVector
)
from django.views.generic import ListView

class SearchView(ListView):
    template_name = 'search.html'
    model = Blog
    paginate_by = 20

    def get_queryset(self):
        query = self.request.GET.get('q')
        vector = SearchVector('title', 'content')
        search_query = SearchQuery(query)
        queryset = Blog.objects.annotate(
            search=SearchRank(vector, search_query)
        ).filter(search=search_query).order_by('-search')
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['query'] = self.request.GET.get('q')
        return context

在搜索页面中,我们可以使用Django模板语言来展示搜索结果:

{% extends 'base.html' %}

{% block content %}
  <form method="get">
    <div class="form-group">
      <input type="text" name="q" class="form-control" placeholder="Search" value="{{ query }}">
    </div>
    <button type="submit" class="btn btn-primary mb-2">Search</button>
  </form>

  <div class="list-group mt-3">
    {% for blog in object_list %}
      <a href="{% url 'blog_detail' blog.id %}" class="list-group-item list-group-item-action">
        <h5>{{ blog.title }}</h5>
        <p>{{ blog.content|truncatewords:30 }}</p>
      </a>
    {% empty %}
      <p>No results found.</p>
    {% endfor %}
  </div>

  {% if page_obj.has_other_pages %}
    <nav class="mt-4" aria-label="Page navigation">
      <ul class="pagination">
        {% if page_obj.has_previous %}
          <li class="page-item">
            <a class="page-link" href="?q={{ query }}&amp;page={{ page_obj.previous_page_number }}">Previous</a>
          </li>
        {% endif %}
        {% for page in page_obj.paginator.page_range %}
          {% if page_obj.number == page %}
            <li class="page-item active">
              <a class="page-link" href="#">{{ page }} <span class="sr-only">(current)</span></a>
            </li>
          {% else %}
            <li class="page-item">
              <a class="page-link" href="?q={{ query }}&amp;page={{ page }}">{{ page }}</a>
            </li>
          {% endif %}
        {% endfor %}
        {% if page_obj.has_next %}
          <li class="page-item">
            <a class="page-link" href="?q={{ query }}&amp;page={{ page_obj.next_page_number }}">Next</a>
          </li>
        {% endif %}
      </ul>
    </nav>
  {% endif %}
{% endblock %}

因此,如果我们使用上面的代码,当用户在搜索框中输入“pidancode.com”或“皮蛋编程”时,会在模型中搜索包含这些关键词的标题和内容,并按相关性排序呈现结果。

相关文章