Django利用elasticsearch(搜索引擎)实现搜索功能


Posted in Python onNovember 26, 2020

 1、在Django配置搜索结果页的路由映射

"""pachong URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
 https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
 1. Add an import: from my_app import views
 2. Add a URL to urlpatterns: url(r'^/pre>, views.home, name='home')
Class-based views
 1. Add an import: from other_app.views import Home
 2. Add a URL to urlpatterns: url(r'^/pre>, Home.as_view(), name='home')
Including another URLconf
 1. Import the include() function: from django.conf.urls import url, include
 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app1 import views

urlpatterns = [
 url(r'^admin/', admin.site.urls),
 url(r'^/pre>, views.indexluoji),
 url(r'^index/', views.indexluoji),
 url(r'^suggest//pre>, views.suggestluoji,name="suggest"),  # 搜索字段补全请求
 url(r'^search//pre>, views.searchluoji,name="search"),  # 搜索

]

2、编写逻辑处理函数

在逻辑处理函数里实现搜索数据

(1)获取到用户的搜索词

(2)利用原生的elasticsearch(搜索引擎)接口,实现搜索,注明:elasticsearch-dsl就是在原生的elasticsearch上做了封装

Elasticsearch()方法,连接原生的elasticsearch服务器

search()方法,原生elasticsearch查询方法,支持原生的elasticsearch查询语句,返回的原生语句结果也就是字典形式的数据

在查询语句里进行关键词高亮处理

将查询到的结果,循环获取到后返回到html页面

from django.shortcuts import render

# Create your views here.
from django.shortcuts import render,HttpResponse
from django.views.generic.base import View
from app1.models import lagouType    # 导入操作elasticsearch(搜索引擎)类
import json
from elasticsearch import Elasticsearch   # 导入原生的elasticsearch(搜索引擎)接口
client = Elasticsearch(hosts=["127.0.0.1"])  # 连接原生的elasticsearch

def indexluoji(request):
 print(request.method) # 获取用户请求的路径
 return render(request, 'index.html')

def suggestluoji(request):          # 搜索自动补全逻辑处理
 key_words = request.GET.get('s', '')      # 获取到请求词
 re_datas = []
 if key_words:
  s = lagouType.search()         # 实例化elasticsearch(搜索引擎)类的search查询
  s = s.suggest('my_suggest', key_words, completion={
   "field": "suggest", "fuzzy": {
    "fuzziness": 1
   },
   "size": 5
  })
  suggestions = s.execute_suggest()
  for match in suggestions.my_suggest[0].options:
   source = match._source
   re_datas.append(source["title"])
 return HttpResponse(json.dumps(re_datas), content_type="application/json")

def searchluoji(request):          # 搜索逻辑处理
 key_words = request.GET.get('q', '')      # 获取到请求词
 response = client.search(         # 原生的elasticsearch接口的search()方法,就是搜索,可以支持原生elasticsearch语句查询
  index="lagou",           # 设置索引名称
  doc_type="biao",          # 设置表名称
  body={             # 书写elasticsearch语句
   "query": {
    "multi_match": {        # multi_match查询
     "query": key_words,       # 查询关键词
     "fields": ["title", "description"]   # 查询字段
    }
   },
   "from": 0,           # 从第几条开始获取
   "size": 10,           # 获取多少条数据
   "highlight": {          # 查询关键词高亮处理
    "pre_tags": ['<span class="keyWord">'],   # 高亮开始标签
    "post_tags": ['</span>'],      # 高亮结束标签
    "fields": {          # 高亮设置
     "title": {},        # 高亮字段
     "description": {}       # 高亮字段
    }
   }
  }
 )
 total_nums = response["hits"]["total"]      # 获取查询结果的总条数
 hit_list = []            # 设置一个列表来储存搜索到的信息,返回给html页面
 for hit in response["hits"]["hits"]:      # 循环查询到的结果
  hit_dict = {}           # 设置一个字典来储存循环结果
  if "title" in hit["highlight"]:       # 判断title字段,如果高亮字段有类容
   hit_dict["title"] = "".join(hit["highlight"]["title"])  # 获取高亮里的title
  else:
   hit_dict["title"] = hit["_source"]["title"]     # 否则获取不是高亮里的title

  if "description" in hit["highlight"]:       # 判断description字段,如果高亮字段有类容
   hit_dict["description"] = "".join(hit["highlight"]["description"])[:500] # 获取高亮里的description
  else:
   hit_dict["description"] = hit["_source"]["description"]  # 否则获取不是高亮里的description

  hit_dict["url"] = hit["_source"]["url"]       # 获取返回url

  hit_list.append(hit_dict)          # 将获取到内容的字典,添加到列表
 return render(request, 'result.html', {"all_hits": hit_list, "key_words": key_words})  #显示页面和将列表和搜索词返回到html

3、html页面接收搜索结果

注意:因为Django实现了防止恶意代码写入,凡是通过变量传输到html页面的html类型代码,将会被自动转换成字符串方式显示,索引我们需要在接收变量的字段用:{% autoescape off %} {{ 接收变量 }} {% endautoescape %},来显示html代码,

搜索后因为进行了一次跳转,所以搜索框里的搜索词将不存在,我们需要在传递搜索结果到页面的时候,将搜索词也传递进来填充到搜索框

<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml">
{#引入静态文件路径#}
{% load staticfiles %}
<head>
<meta http-equiv="X-UA-Compatible" content="IE=emulateIE7" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>python-lcv-search搜索引擎</title>
<link href="{% static 'css/style.css'%}" rel="external nofollow" rel="stylesheet" type="text/css" />
<link href="{% static 'css/result.css'%}" rel="external nofollow" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="container">
 <div id="hd" class="ue-clear">
  <a href="/" rel="external nofollow" ><div class="logo"></div></a>
  <div class="inputArea">
   <input type="text" class="searchInput" value="{{ key_words }}"/>
   <input type="button" class="searchButton" onclick="add_search()"/>
  </div>
 </div>
 <div class="nav">
  <ul class="searchList">
   <li class="searchItem current" data-type="article">文章</li>
   <li class="searchItem" data-type="question">问答</li>
   <li class="searchItem" data-type="job">职位</li>
  </ul>
 </div>
 <div id="bd" class="ue-clear">
  <div id="main">
   <div class="sideBar">

    <div class="subfield">网站</div>
    <ul class="subfieldContext">
     <li>
      <span class="name">伯乐在线</span>
      <span class="unit">(None)</span>
     </li>
     <li>
      <span class="name">知乎</span>
      <span class="unit">(9862)</span>
     </li>
     <li>
      <span class="name">拉勾网</span>
      <span class="unit">(9862)</span>
     </li>
     <li class="more">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" >
       <span class="text">更多</span>
       <i class="moreIcon"></i>
      </a>
     </li>
    </ul>

    <div class="sideBarShowHide">
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="icon"></a>
    </div>
   </div>
   <div class="resultArea">
    <p class="resultTotal">
     <span class="info">找到约 <span class="totalResult">45</span> 条结果(用时<span class="time">0.643128</span>秒),共约<span class="totalPage">5</span>页</span>
    </p>
    <div class="resultList">
     {% for hit in all_hits %}
     <div class="resultItem">
       <div class="itemHead">
        <a href="{% autoescape off %} {{ hit.url }} {% endautoescape %}" rel="external nofollow" target="_blank" class="title">{% autoescape off %} {{ hit.title }} {% endautoescape %}</a>
        <span class="divsion">-</span>
        <span class="fileType">
         <span class="label">来源:</span>
         <span class="value">网络</span>
        </span>
        <span class="dependValue">
         <span class="label">得分:</span>
         <span class="value">3.401155</span>
        </span>
       </div>
       <div class="itemBody">
        {% autoescape off %} {{ hit.description }} {% endautoescape %}
       </div>
      </div>
     {% endfor %}
    </div>
    <!-- 分页 -->
    <div class="pagination ue-clear"></div>
    <!-- 相关搜索 -->

   </div>
   <div class="historyArea">
    <div class="hotSearch">
     <h6>热门搜索</h6>
     <ul class="historyList">

       <li><a href="/search?q=linux" rel="external nofollow" >linux</a></li>

     </ul>
    </div>
    <div class="mySearch">
     <h6>我的搜索</h6>
     <ul class="historyList">

     </ul>
    </div>
   </div>
  </div><!-- End of main -->
 </div><!--End of bd-->
</div>

<div id="foot">Copyright ©projectsedu.com 版权所有 E-mail:admin@projectsedu.com</div>
</body>
<script type="text/javascript" src="{% static 'js/jquery.js'%}"></script>
<script type="text/javascript" src="{% static 'js/global.js'%}"></script>
<script type="text/javascript" src="{% static 'js/pagination.js'%}"></script>
<script type="text/javascript">
 var search_url = "/search/"

 $('.searchList').on('click', '.searchItem', function(){
  $('.searchList .searchItem').removeClass('current');
  $(this).addClass('current'); 
 });

 $.each($('.subfieldContext'), function(i, item){
  $(this).find('li:gt(2)').hide().end().find('li:last').show();  
 });

 function removeByValue(arr, val) {
  for(var i=0; i<arr.length; i++) {
  if(arr[i] == val) {
   arr.splice(i, 1);
   break;
  }
  }
 }
 $('.subfieldContext .more').click(function(e){
  var $more = $(this).parent('.subfieldContext').find('.more');
  if($more.hasClass('show')){

   if($(this).hasClass('define')){
    $(this).parent('.subfieldContext').find('.more').removeClass('show').find('.text').text('自定义');
   }else{
    $(this).parent('.subfieldContext').find('.more').removeClass('show').find('.text').text('更多'); 
   }
   $(this).parent('.subfieldContext').find('li:gt(2)').hide().end().find('li:last').show();
  }else{
   $(this).parent('.subfieldContext').find('.more').addClass('show').find('.text').text('收起');
   $(this).parent('.subfieldContext').find('li:gt(2)').show(); 
  }

 });

 $('.sideBarShowHide a').click(function(e) {
  if($('#main').hasClass('sideBarHide')){
   $('#main').removeClass('sideBarHide');
   $('#container').removeClass('sideBarHide');
  }else{
   $('#main').addClass('sideBarHide'); 
   $('#container').addClass('sideBarHide');
  }

 });
 var key_words = "java"
 //分页
 $(".pagination").pagination(45, {
  current_page :0, //当前页码
  items_per_page :10,
  display_msg :true,
  callback :pageselectCallback
 });
 function pageselectCallback(page_id, jq) {
  window.location.href=search_url+'?q='+key_words+'&p='+page_id
 }

 setHeight();
 $(window).resize(function(){
  setHeight(); 
 });

 function setHeight(){
  if($('#container').outerHeight() < $(window).height()){
   $('#container').height($(window).height()-33);
  } 
 }
</script>
<script type="text/javascript">
 $('.searchList').on('click', '.searchItem', function(){
  $('.searchList .searchItem').removeClass('current');
  $(this).addClass('current');
 });

 // 联想下拉显示隐藏
 $('.searchInput').on('focus', function(){
  $('.dataList').show()
 });

 // 联想下拉点击
 $('.dataList').on('click', 'li', function(){
  var text = $(this).text();
  $('.searchInput').val(text);
  $('.dataList').hide()
 });

 hideElement($('.dataList'), $('.searchInput'));
</script>
<script>
 var searchArr;
 //定义一个search的,判断浏览器有无数据存储(搜索历史)
 if(localStorage.search){
  //如果有,转换成 数组的形式存放到searchArr的数组里(localStorage以字符串的形式存储,所以要把它转换成数组的形式)
  searchArr= localStorage.search.split(",")
 }else{
  //如果没有,则定义searchArr为一个空的数组
  searchArr = [];
 }
 //把存储的数据显示出来作为搜索历史
 MapSearchArr();

 function add_search(){
  var val = $(".searchInput").val();
  if (val.length>=2){
   //点击搜索按钮时,去重
   KillRepeat(val);
   //去重后把数组存储到浏览器localStorage
   localStorage.search = searchArr;
   //然后再把搜索内容显示出来
   MapSearchArr();
  }

  window.location.href=search_url+'?q='+val+"&s_type="+$(".searchItem.current").attr('data-type')

 }

 function MapSearchArr(){
  var tmpHtml = "";
  var arrLen = 0
  if (searchArr.length > 6){
   arrLen = 6
  }else {
   arrLen = searchArr.length
  }
  for (var i=0;i<arrLen;i++){
   tmpHtml += '<li><a href="/search?q='+searchArr[i]+'" rel="external nofollow" >'+searchArr[i]+'</a></li>'
  }
  $(".mySearch .historyList").append(tmpHtml);
 }
 //去重
 function KillRepeat(val){
  var kill = 0;
  for (var i=0;i<searchArr.length;i++){
   if(val===searchArr[i]){
    kill ++;
   }
  }
  if(kill<1){
   searchArr.unshift(val);
  }else {
   removeByValue(searchArr, val)
   searchArr.unshift(val)
  }
 }
</script>
</html>

最终效果

Django利用elasticsearch(搜索引擎)实现搜索功能

到此这篇关于Django利用elasticsearch(搜索引擎)实现搜索功能的文章就介绍到这了,更多相关Django elasticsearch 搜索 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现在字符串中查找子字符串的方法
Jul 11 Python
详解python中xlrd包的安装与处理Excel表格
Dec 16 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
Jun 02 Python
python3库numpy数组属性的查看方法
Apr 17 Python
对python 各种删除文件失败的处理方式分享
Apr 24 Python
ubuntu17.4下为python和python3装上pip的方法
Jun 12 Python
python3.6的venv模块使用详解
Aug 01 Python
python实现的MySQL增删改查操作实例小结
Dec 19 Python
python 获得任意路径下的文件及其根目录的方法
Feb 16 Python
DjangoWeb使用Datatable进行后端分页的实现
May 18 Python
opencv读取视频并保存图像的方法
Jun 04 Python
Python中seaborn库之countplot的数据可视化使用
Jun 11 Python
python模拟点击在ios中实现的实例讲解
Nov 26 #Python
如何在 Matplotlib 中更改绘图背景的实现
Nov 26 #Python
python 实现超级玛丽游戏
Nov 25 #Python
python 制作简单的音乐播放器
Nov 25 #Python
python中绕过反爬虫的方法总结
Nov 25 #Python
pycharm激活码免费分享适用最新pycharm2020.2.3永久激活
Nov 25 #Python
python爬虫泛滥的解决方法详解
Nov 25 #Python
You might like
PHP安装攻略:常见问题解答(二)
2006/10/09 PHP
防止用户利用PHP代码DOS造成用光网络带宽
2011/03/01 PHP
php实现XSS安全过滤的方法
2015/07/29 PHP
Thinkphp3.2.3分页使用实例解析
2016/07/28 PHP
Bootstrap+PHP实现多图上传功能实例详解
2018/04/08 PHP
jQuery 加上最后自己的验证
2009/11/04 Javascript
extjs中grid中嵌入动态combobox的应用
2011/01/01 Javascript
使用jQuery操作Cookies的实现代码
2011/10/09 Javascript
JavaScript中__proto__与prototype的关系深入理解
2012/12/04 Javascript
JS去除右边逗号的简单方法
2013/07/03 Javascript
javascript函数重载解决方案分享
2014/02/19 Javascript
jquery实现在页面加载的时自动为日期插件添加当前日期
2014/08/20 Javascript
jQuery中:empty选择器用法实例
2014/12/30 Javascript
详解微信小程序设置底部导航栏目方法
2017/06/29 Javascript
Angularjs单选框相关的示例代码
2017/08/17 Javascript
使用socket.io实现简单聊天室案例
2018/01/02 Javascript
react中fetch之cors跨域请求的实现方法
2018/03/14 Javascript
Nodejs处理异常操作示例
2018/12/25 NodeJs
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
2020/04/25 Javascript
js 数组当前行添加数据方法详解
2020/07/28 Javascript
[05:22]DOTA2 2015国际邀请赛中国区预选赛首日TOP10
2015/05/26 DOTA
[02:59]DOTA2完美大师赛主赛事第三日精彩集锦
2017/11/25 DOTA
Python爬虫番外篇之Cookie和Session详解
2017/12/27 Python
python flask 如何修改默认端口号的方法步骤
2019/07/12 Python
Django Form常用功能及代码示例
2020/10/13 Python
python SOCKET编程基础入门
2021/02/27 Python
纯CSS3实现地球自转实现代码(图文教程附送源码)
2012/12/26 HTML / CSS
canvas 阴影和图形变换的示例代码
2018/01/02 HTML / CSS
《晚上的太阳》教学反思
2014/04/23 职场文书
出售房屋协议书范本
2014/10/06 职场文书
2015元旦文艺汇演主持稿(开场白+结束语)
2014/12/14 职场文书
大足石刻导游词
2015/02/02 职场文书
2015年综治宣传月活动总结
2015/03/25 职场文书
建筑技术负责人岗位职责
2015/04/13 职场文书
CSS 使用 resize 实现图片拖拽切换预览功能(强大功能)
2021/08/23 HTML / CSS
Go语言测试库testify使用学习
2022/07/23 Golang