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挑选文件夹里宽大于300图片的方法
Mar 05 Python
python梯度下降法的简单示例
Aug 31 Python
使用pyinstaller打包PyQt4程序遇到的问题及解决方法
Jun 24 Python
Python queue队列原理与应用案例分析
Sep 27 Python
python中设置超时跳过,超时退出的方式
Dec 13 Python
基于python 取余问题(%)详解
Jun 03 Python
浅谈keras.callbacks设置模型保存策略
Jun 18 Python
如何完美的建立一个python项目
Oct 09 Python
python+excel接口自动化获取token并作为请求参数进行传参操作
Nov 10 Python
python中的class_static的@classmethod的巧妙用法
Jun 22 Python
Python中re模块的元字符使用小结
Apr 07 Python
python模拟浏览器 使用selenium进入好友QQ空间并留言
Apr 12 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下获取Discuz论坛登录用户名、用户组、用户ID等信息的实现代码
2010/12/29 PHP
php程序的国际化实现方法(利用gettext)
2011/08/14 PHP
利用php递归实现无限分类 格式化数组的详解
2013/06/08 PHP
PHP SESSION机制的理解与实例
2019/03/22 PHP
JavaScript Undefined,Null类型和NaN值区别
2008/10/22 Javascript
cnblogs csdn 代码运行框实现代码
2009/11/02 Javascript
jQuery布局插件UI Layout简介及使用方法
2013/04/03 Javascript
Javascript加载速度慢的解决方案
2014/03/11 Javascript
jQuery实现的在线答题功能
2015/04/12 Javascript
QQ登录背景闪动效果附效果演示源码下载
2015/09/22 Javascript
java必学必会之static关键字
2015/12/03 Javascript
基于javascript实现简单计算器功能
2016/01/03 Javascript
基于javascript实现彩票随机数生成(升级版)
2020/04/17 Javascript
完美解决手机网页中输入框被输入法遮挡的问题
2017/12/19 Javascript
javascript异步处理与Jquery deferred对象用法总结
2019/06/04 jQuery
javascript实现固定侧边栏
2021/02/09 Javascript
Python中使用动态变量名的方法
2014/05/06 Python
跟老齐学Python之编写类之四再论继承
2014/10/11 Python
Python在线运行代码助手
2016/07/15 Python
Python连接phoenix的方法示例
2017/09/29 Python
python里使用正则表达式的组嵌套实例详解
2017/10/24 Python
对Python 窗体(tkinter)树状数据(Treeview)详解
2018/10/11 Python
使用Python抓取豆瓣影评数据的方法
2018/10/17 Python
PyQt中使用QtSql连接MySql数据库的方法
2020/07/28 Python
CSS3实现可关闭的下拉手风琴菜单效果
2015/08/31 HTML / CSS
NFL墨西哥官方商店:Tienda NFL
2017/11/28 全球购物
"火柴棍式"程序员面试题
2014/03/16 面试题
如何进行Linux分区优化
2013/02/12 面试题
请写出一段Python代码实现删除一个list里面的重复元素
2015/12/29 面试题
工业自动化专业毕业生推荐信
2013/11/18 职场文书
勤奋学习演讲稿
2014/05/10 职场文书
公司领导班子召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
2014矛盾纠纷排查调处工作总结
2014/12/09 职场文书
银行中层干部培训心得体会
2016/01/11 职场文书
关于golang高并发的实现与注意事项说明
2021/05/08 Golang
Golang解析JSON对象
2022/04/30 Golang