一、搜索功能分析
思考:如果我们要做一个通过关键词搜索文章的功能,需要搜索哪些字段,以及使用什么技术方案?
搜索字段:
1,字段
2,内容
3,作者
技术方案:
1,mysql的模糊查询%like%
1,优点:实现起来简单
2,缺点:数据量比较大的情况下,查询效率极低
2,全文检索引擎
1,优点:专业的全文检索引擎,效率高
2,缺点:实现起来比较复杂
选择使用全文检索引擎,自行实现django框架和全文检索引擎的代码比较麻烦,选用django的
第三方包djangohaystack。它支持多钟全文检索引擎,本项目选择最流行的全文检索引擎之一
elasticsearch
二、elasticsearch介绍
elasticsearch原理:http://developer.51cto.com/art/201904/594615.htm
三、docker介绍
1.docker介绍与安装
~介绍
1,什么是docker?
~简化创建,部署,运行应用程序的一个工具
~打包应用程序所需的库和依赖环境
~精简的虚拟机
2.为什么使用docher?
流行、方便、强大
3.docker vs 虚拟机
体积更小、运行更快、集成扩展更好
4.docker架构
~架构
~客户端
~守护进程
~仓库
~docker对象
~镜像 精简linux
~容器
~服务
~docker Hub
安装
官方安装文档:https://www.docker.com/
lsb_release -a #查看系统信息
五、新闻搜索功能实现
1,业务流程分析
判断是否传递查询参数q
如果没有传递q,则直接返回热门新闻数据
如果没有传递,则返回查询结果
2,接口设计
1.接口说明:
类目 说明
请求方法 GET
url定义 /news/search/
参数格式 查询参数
2.参数说明:
参数名 类型 是否必须 描述
q 字符串 否 查询的关键字
page 整数 否 页码
3.返回结果:
搜索页面html
1.创建haystack数据模型
news/search_indexes 文件代码
from haystack import indexesfrom .models import Newsclass NewsIndex(indexes.SearchIndex, indexes.Indexable): """ 这个模型的作用类似于django的模型,它告诉haystack哪些数据会被 放到查询返回的模型对象中,以及通过哪些字段进行索引和查询 """ text = indexes.CharField(document=True, use_template=True) id = indexes.CharField(model_attr='id') title = indexes.CharField(model_attr='title') digest = indexes.CharField(model_attr='digest') content = indexes.CharField(model_attr='content') image_url = indexes.CharField(model_attr='image_url') def get_model(self): """ 返回建立索引的模型 :return: """ return News def index_queryset(self, using=None): """ 返回要建立索引的数据查询集 :param using: :return: """ return self.get_model().objects.filter(is_delete=False)2,创建索引数据模版 templates/search/indexes/news/news_text.txt 文件
{{ object.title }} {{ object.digest }} {{ object.content }} {{ object.author.username }}
3,创建索引
虚拟机进入项目根目录
运行命令:python manage.py -h
python manage.py rebuild_index
代码:
news/templatetags/news_template_filters.py
from django import templateregister = template.Library()@register.filter()def page_bar(page): page_list = [] if page.number != 1: page_list.append(1) if page.number - 3 > 1: page_list.append('...') if page.number - 2 > 1: page_list.append(page.number - 2) if page.number - 1 > 1: page_list.append(page.number -1) page_list.append(page.number) if page.paginator.num_pages > page.number + 1: page_list.append(page.number + 1) if page.paginator.num_pages > page.number + 2: page_list.append(page.number + 2) if page.paginator.num_pages > page.number + 3: page_list.append('...') if page.paginator.num_pages != page.number: page_list.append(page.paginator.num_pages) return page_listapps/news/views.py 代码
class NewsSearchView(SearchView): """ 新闻搜索视图 url: /news/search/ """ # 配置搜索模板文件 template_name = 'news/search.html' def get(self, request, *args, **kwargs): # 1. 获取查询参数 query = request.GET.get('q') if not query: # 2. 如果没有查询数 # 返回热门新闻 hot_news = HotNews.objects.select_related('news__tag').only('news__title', 'news__image_url', 'news_id', 'news__tag__name').filter(is_delete=False).order_by('priority', '-news__clicks') # 分页 paginator = Paginator(hot_news, settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE) try: page = paginator.get_page(int(request.GET.get('page'))) except Exception as e: page = paginator.get_page(1) return render(request, self.template_name, context={ 'page': page, 'query': query }) else: # 3. 如果有怎么办 return super().get(request, *args, **kwargs) def get_context_data(self, *args, **kwargs): """ 在context中添加变量page :param args: :param kwargs: :return: """ context = super().get_context_data(*args, **kwargs) if context['page_obj']: context['page'] = context['page_obj'] return context