1. 程式人生 > 程式設計 >Django利用elasticsearch(搜尋引擎)實現搜尋功能

Django利用elasticsearch(搜尋引擎)實現搜尋功能

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/',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">找到約&nbsp;<span class="totalResult">45</span>&nbsp;條結果(用時<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 &copy;projectsedu.com 版權所有 E-mail:[email protected]</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',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 搜尋 內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!