各种搜索引擎:whoosh,Solr, Sphinx, Xapian。。
引擎的比较:https://blog.csdn.net/Akira_Rexlee/article/details/85163898
elasticsearch 官网地址: https://docs.docker.com/install/linux/docker-ce/ubuntu/
0. 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
1. 更新apt:
sudo apt-get update
2. 添加证书安装包以允许apt通过HTTPS:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
3. 添加Docker的官方GPG密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
4. 添加仓库。
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) \stable"
5. 安装docker ce
sudo apt-get install docker-ce docker-ce-cli containerd.io
6. 测试
sudo docker run hello-world
7. 添加当前用户到 docker 用户组
sudo usermod -aG docker pyvip
8.docker --version查看版本 docker images查看运行的容器
docker stop tbd8关闭容器 tbd8
/####################################/
# 拉取镜像到本地仓库使用docker安装elasticsearch 搜索引擎
# docker image pull delron/elasticsearch-ik:2.4.6-1.0 很慢!!
xshell中用rz命令导入下载好的这个文件压缩包
然后导入镜像: docker load -i elasticsearch-ik-2.4.6_docker.tar
然后rz导入elasticsearch.zip文件接着操作unzip elasticsearch.zip解压文件等
里面的配置文件 端口已改为8002,原来9002??
创建docker容器并运行
# 根据拉取到本地的镜像创建容器,需要将/home/bd/elasticsearch/config配置文件所在目录修改为你自己的路径
docker run -dti --network=host --name=elasticsearch -v /home/pyvip/elasticsearch/config:/usr/share/elasticsearch/config delron/elasticsearch-ik:2.4.6-1.0
下面容器写了up才是启动状态的
# 运行如下命令,如果有显示则elasticsearch配置成功curl 127.0.0.1:8002
d.进入项目虚拟环境中,安装相关包
```linux
# 进入项目虚拟环境
workon taka
pip install django-haystack 安装前更新下pip pip install --upgrade pip
pip install elasticsearch==2.4.1 就这个版本 比较稳定!!
接着在settings.py文件中加入如下配置:
```python
INSTALLED_APPS = [
'haystack',
]
ELASTICSEARCH_DSL = {
'default': {
'hosts': '127.0.0.1:8002'
},
}
# Haystack
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://127.0.0.1:8002/', # 此处为elasticsearch运行的服务器ip地址,端口号默认为9200
'INDEX_NAME': 'dj_pre_class', # 指定elasticsearch建立的索引库的名称
},
}
# 设置每页显示的数据量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5
# 当数据库改变时,会自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
然后是后端的配置使用
```python
# 在apps/news/search_indexes.py中创建如下类:(名称固定为search_indexes.py)
from haystack import indexes
# from haystack import site
from .models import News
class NewsIndex(indexes.SearchIndex, indexes.Indexable):#NewsIndex名字固定!!
"""
News索引数据模型类
"""
text = indexes.CharField(document=True, use_template=True)
id = indexes.IntegerField(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')
# comments = indexes.IntegerField(model_attr='comments')
def get_model(self):
"""返回建立索引的模型类
"""
return News
def index_queryset(self, using=None):
"""返回要建立索引的数据查询集
"""
return self.get_model().objects.filter(is_delete=False, tag_id=1)
```
```python app news中views里加的
from haystack.views import SearchView as _SearchView
class SearchView(_SearchView):
# 模版文件
template = 'news/search.html'
# 重写响应方式,如果请求参数q为空,返回模型News的热门新闻数据,否则根据参数q搜索相关数据
def create_response(self):
kw = self.request.GET.get('q', '')
if not kw:
show_all = True
hot_news = models.HotNews.objects.select_related('news'). \
only('news__title', 'news__image_url', 'news__id'). \
filter(is_delete=False).order_by('priority', '-news__clicks')
paginator = Paginator(hot_news, settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE)
try:
page = paginator.page(int(self.request.GET.get('page', 1)))
except PageNotAnInteger:
# 如果参数page的数据类型不是整型,则返回第一页数据
page = paginator.page(1)
except EmptyPage:
# 用户访问的页数大于实际页数,则返回最后一页的数据
page = paginator.page(paginator.num_pages)
return render(self.request, self.template, locals())
else:
show_all = False
qs = super(SearchView, self).create_response()
return qs
```
```python
# 创建templates/search/indexes/news/news_text.txt文件(文件名为:app名/模型类小写名_text.txt)
这三段为文件的内容:
{{ object.title }}
{{ object.digest }}
{{ object.content }}
```
```python
# 在apps/news/urls.py中
urlpatterns = [
path('search/', views.SearchView(), name='search'),
]
```
```linux
# 在虚拟机中执行如下命令,生成索引
python manage.py rebuild_index
```
####.前端功能实现
```html
<!-- 在templates/news1/search.html中加入如下代码: -->
<div class="main-contain ">
<!-- search-box start -->
<div class="search-box">
<form action="" style="display: inline-flex;">
<input type="search" placeholder="请输入要搜索的内容" name="q" class="search-control">
<input type="submit" value="搜索" class="search-btn">
</form>
<!-- 可以用浮动 垂直对齐 以及 flex -->
</div>
<!-- search-box end -->
<!-- content start -->
<div class="content">
<!-- search-list start -->
{% if not show_all %}
<div class="search-result-list">
<h2 class="search-result-title">
搜索结果 <span style="font-weight: 700;color: #ff6620;">{{ paginator.num_pages }}</span>页
</h2>
<ul class="news-list">
{# 导入自带高亮功能 #}
{% load highlight %}
{% for one_news in page.object_list %}
<li class="news-item clearfix">
<a href="{% url 'news:news_detail' one_news.id %}" class="news-thumbnail"
target="_blank">
<img src="{{ one_news.object.image_url }}">
</a>
<div class="news-content">
<h4 class="news-title">
<a href="{% url 'news:news_detail' one_news.id %}">
{% highlight one_news.title with query %}
</a>
</h4>
<p class="news-details">{% highlight one_news.digest with query %}</p>
<div class="news-other">
<span class="news-type">{{ one_news.object.tag.name }}</span>
<span class="news-time">{{ one_news.object.update_time }}</span>
<span
class="news-author">{% highlight one_news.object.author.username with query %}
</span>
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
{% else %}
<div class="news-contain">
<div class="hot-recommend-list">
<h2 class="hot-recommend-title">热门推荐</h2>
<ul class="news-list">
{% for one_hotnews in page.object_list %}
<li class="news-item clearfix">
<a href="#" class="news-thumbnail">
<img src="{{ one_hotnews.news.image_url }}">
</a>
<div class="news-content">
<h4 class="news-title">
<a href="{% url 'news:news_detail' one_hotnews.news.id %}">{{ one_hotnews.news.title }}</a>
</h4>
<p class="news-details">{{ one_hotnews.news.digest }}</p>
<div class="news-other">
<span class="news-type">{{ one_hotnews.news.tag.name }}</span>
<span class="news-time">{{ one_hotnews.update_time }}</span>
<span class="news-author">{{ one_hotnews.news.author.username }}</span>
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
<!-- search-list end -->
<!-- news-contain start -->
{# 分页导航 #}
<div class="page-box" id="pages">
<div class="pagebar" id="pageBar">
<a class="a1">{{ page.paginator.count }}条</a>
{# 上一页的URL地址 #}
{% if page.has_previous %}
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ page.previous_page_number }}"
class="prev">上一页</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ page.previous_page_number }}" class="prev">上一页</a>
{% endif %}
{% endif %}
{# 列出所有的URL地址 #}
{% for num in page.paginator.page_range|slice:":10" %}
{% if num == page.number %}
<span class="sel">{{ page.number }}</span>
{% else %}
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ num }}"
target="_self">{{ num }}</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ num }}" target="_self">{{ num }}</a>
{% endif %}
{% endif %}
{% endfor %}
{# 如果页数大于10,则打两点 #}
{% if page.paginator.num_pages > 10 %}
..
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ page.paginator.num_pages }}"
target="_self">{{ page.paginator.num_pages }}</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ page.paginator.num_pages }}"
target="_self">{{ page.paginator.num_pages }}</a>
{% endif %}
{% endif %}
{# 下一页的URL地址 #}
{% if page.has_next %}
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ page.next_page_number }}"
class="next">下一页</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ page.next_page_number }}" class="next">下一页</a>
{% endif %}
{% endif %}
</div>
</div>
<!-- news-contain end -->
</div>
<!-- content end -->
</div>
```
```css
/* 在static/css/news/search.css中加入如下代码: */
/* === current index start === */
#pages {
padding: 32px 0 10px;
}
.page-box {
text-align: center;
/*font-size: 14px;*/
}
#pages a.prev, a.next {
width: 56px;
padding: 0
}
#pages a {
display: inline-block;
height: 26px;
line-height: 26px;
background: #fff;
border: 1px solid #e3e3e3;
text-align: center;
color: #333;
padding: 0 10px
}
#pages .sel {
display: inline-block;
height: 26px;
line-height: 26px;
background: #0093E9;
border: 1px solid #0093E9;
color: #fff;
text-align: center;
padding: 0 10px
}
.highlighted{
color:coral;
mso-ansi-font-weight: bold;
}
/* === current index end === */
```